Wow Matthias, you are like the pied piper of weird == implementations!

I'm glad you were able to put those in the discussion. To check into Python
and its standard modules itself ... I can imagine putting together a grep
type thing to just dig all the __eq__ out of there and look at them. Like
how many are there I wonder? I suppose the tend to be implemented on the C
side anyway.

Best,

Nick

On Tue, Aug 31, 2021 at 5:17 PM Matthias Bussonnier <
bussonniermatth...@gmail.com> wrote:

> > Are there other such classes?
>
> from the top of my head, Pandas:
>
> In [13]: pd.DataFrame([[1,2], [3, 4]]) == None
> Out[13]:
>        0      1
> 0  False  False
> 1  False  False
>
> and any zarr container, or xarray will behave like numpy and broadcast.
> Ah, that means probably Dask, and Ray. Also maybe CuPy ?
> But I'm not going to list all that behave like numpy or pandas, but
> that's a big chunk of things that return non boolean values.
>
> Let's grep into my dev folder for other weird __eq__
>
> $ rg  'def __eq__' -A3
>
> ... stuff, let's pick a few:
>
> sympy.physics.optics.Medium:
>
>     def __eq__(self, other):
>         return self.refractive_index == other.refractive_index
>
> Will crash with None has no attribute refractive_index,
>
> IPython's internal Completions objects around Jedi also assume they
> are compared against instances of the same class and will crash, but
> likely with 'NoneType' object is not subscriptable.
>
> matplotlib FontProperties have a small but non-zero change of telling
> you that the current (object == None) is True as it compares hashes,
> so if the hash of the FontProp is the same as None... well.
>
>
> Basically anything that implements __eq__ and assumes it will be
> compared only against things that are of the same type will not be
> happy to be compared with None using ==.
> or implement broadcasting like abilities.
> --
> Matthias
>
> On Tue, 31 Aug 2021 at 16:22, Nick Parlante <n...@cs.stanford.edu> wrote:
> >
> > To argue that == is unreliable, I think Matthias has the best,
> non-contrived example with numpy, which I did not know about:
> >
> > >>> x = np.array([1, 2, 3])
> > >>> x == None
> > array([False, False, False])
> >
> > This certainly is a good example of == not being reliable. Point taken
> there.
> >
> > Are there other such classes? Like if I write code that just uses Python
> and its standard library classes, can I get a value where == None is flaky
> like the numpy example? I wouldn't think so, just as a matter of
> principle-of-least-surprise API design. Anyway, that would be very
> interesting example to argue against my claim that == None is reliable.
> >
> > Best,
> >
> > Nick
> >
> > On Mon, Aug 30, 2021 at 12:06 PM Matthias Bussonnier <
> bussonniermatth...@gmail.com> wrote:
> >>
> >> From my point of view as someone who sometimes help  Scientist write
> >> Python, this is a no go, there are too many cases where == and is are
> >> different.
> >>
> >> $ ipython
> >> Python 3.8.5 | packaged by conda-forge | (default, Sep 16 2020,
> 17:43:11)
> >> Type 'copyright', 'credits' or 'license' for more information
> >> IPython 7.25.0 -- An enhanced Interactive Python. Type '?' for help.
> >>
> >> In [1]: import numpy as np
> >>
> >> In [2]: a = np.array([True, False, None])
> >>
> >> In [3]: a == True, a == False, a == None
> >> Out[3]:
> >> (array([ True, False, False]),
> >>  array([False,  True, False]),
> >>  array([False, False,  True]))
> >>
> >> In [4]: a is True, a is False, a is None
> >> Out[4]: (False, False, False)
> >>
> >> if `a == True` can even raise errors when in ifs:
> >>
> >> In [5]: if a == True:
> >>    ...:     pass
> >>    ...:
> >>
> ---------------------------------------------------------------------------
> >> ValueError                                Traceback (most recent call
> last)
> >> <ipython-input-5-59a850ef5f8d> in <module>
> >> ----> 1 if a == True:
> >>       2     pass
> >>       3
> >>
> >> ValueError: The truth value of an array with more than one element is
> >> ambiguous. Use a.any() or a.all()
> >>
> >> Basic types are just too simple to expose the real need between `==`
> >> and `is`, but that's not a reason not to give the right advice from
> >> the start.
> >> IMHO It would be like teaching English and saying that it's ok not to
> >> put s after nouns when there is a number in front as it's obvious
> >> there are many.
> >>
> >> I do understand your concern, but I believe that would be just pushing
> >> the problem to later, when it would be much more difficult to explain
> >> and have students get a wrong mental model from the start, which is
> >> really hard to overcome.
> >>
> >> --
> >> Matthias
> >>
> >> On Mon, 30 Aug 2021 at 11:45, Nick Parlante <n...@cs.stanford.edu>
> wrote:
> >> >
> >> > Hi there python-ideas - I've been teaching Python as a first
> >> > programming language for a few years, and from that experience I want
> >> > to propose a change to PEP8. I'm sure the default position for PEP8 is
> >> > to avoid changing it. However, for this one rule I think a good case
> >> > can be made to make it optional, so let me know what you think.
> >> >
> >> > Let me start with what I've learned from teaching students in Java and
> >> > now in Python. In Java, you use == for ints, but you need to use
> >> > equals() for strings. Of course students screw this up constantly,
> >> > using == in a context that calls for equals() and their code does not
> >> > work right. Then for Java arrays a different comparison function is
> >> > required, and so it goes. To teach comparisons in Python, I simply say
> >> > "just use ==" - it works for ints, for strings, even for lists.
> >> > Students are blown away by how nice and simple this is. This is how
> >> > things should work. Python really gets this right.
> >> >
> >> > So what is the problem?
> >> >
> >> > The problem for Python is what I will call the "mandatory-is" rule in
> >> > PEP8, which reads:
> >> >
> >> > Comparisons to singletons like None should always be done with is or
> >> > is not, never the equality operators.
> >> >
> >> > For the students, this comes up in the first week of the course with
> >> > lines like "if x == None:" which work perfectly with == but should use
> >> > is/is-not for PEP8 conformance.
> >> >
> >> > My guess is that this rule is in PEP8 because, within a Python
> >> > implementation, it is within the programmer's mental model that, say,
> >> > False is a singleton. The mandatory-is rule is in PEP8 to reinforce
> >> > that mental model by requiring the is operator. Plus it probably runs
> >> > a tiny bit faster.
> >> >
> >> > However, for "regular" Python code, not implementing Python, forcing
> >> > the use of is instead of the simpler == is unneeded and unhelpful (and
> >> > analogously forcing "is not" when != works correctly). What is the
> >> > benefit of forcing the is operator there? I would say it spreads an
> >> > awareness of the details of how certain values are allocated within
> >> > Python. That's not much of a benefit, and it's kind of circular. Like
> >> > if programmers were permitted to use ==, they wouldn't need to know
> >> > the details of how Python allocates those values. Being shielded from
> >> > implementation details is a Python strength - think of the Java vs.
> >> > Python story above. Is Java better because it builds an awareness in
> >> > the programmer of the different comparison functions for different
> >> > types? Of course not! Python is better in that case because it lets
> >> > the programmer simply use == and not think about those details.
> >> > Understanding the singleton strategy is important in some corners of
> >> > coding, but forcing the is operator on all Python code is way out of
> >> > proportion to the benefit.
> >> >
> >> > As a practical matter, the way this comes up for my students is that
> >> > IDEs by default will put warning marks around PEP8 violations in their
> >> > code. Mostly this IDE-coaching is very helpful for students learning
> >> > Python. For example, It's great that beginning Python programmers
> >> > learn to put one space around operators right from the first day.
> >> > Having taught thousands of introductory Python students, the one PEP8
> >> > rule that causes problems is this mandatory-is rule.
> >> >
> >> > As a teacher, this is especially jarring since the "just use ==" rule
> >> > is so effortless to use correctly. In contrast, the mandatory-is rule
> >> > adds a little pause where the programmer should think about which
> >> > comparison operator is the correct one to use. It's not hard, but it
> >> > feels unnecessary.
> >> >
> >> > As a contrasting example, in the language C, programmers need to
> >> > understand == vs. is right from the first day. You can't get anything
> >> > done in C without understanding that distinction. However that is just
> >> > not true for regular (not-Python-implementation) Python code, where ==
> >> > works correctly for the great majority of cases.
> >> >
> >> > Here is my proposal:
> >> >
> >> > Add the following parenthetical to the mandatory-is rule: (this rule
> >> > is optional for code that is not part of an implementation of Python).
> >> >
> >> > So in effect, programmers outside of a Python implementation can
> >> > choose to use == or is for the "if x == None:" case. In this way, PEP8
> >> > conforming code before the change is still conforming. Moving forward,
> >> > I would expect that regular code will trend towards using == in such a
> >> > case, reserving is for the rare cases where it is needed for
> >> > correctness.
> >> >
> >> > PEP8 was originally just for Python implementations, so why is this
> >> > change needed? Because as a practical matter, the vast majority of
> >> > code that is using PEP8 is not part of a Python implementation. This
> >> > may not have been the original mission of PEP8, but it is how things
> >> > have worked out.
> >> >
> >> > Now we are in a situation where the rules in PEP8 are sent out to this
> >> > ocean of Python programmers of many different ability levels writing
> >> > regular code that is not a Python implementation. One could imagine a
> >> > separate PEP800 style guide for regular code, but we don't need to do
> >> > that, because in almost all cases PEP8 works great for regular code. I
> >> > have taught thousands of new Python programmers, and the only place
> >> > where PEP8 serves them poorly is this mandatory-is rule. Therefore
> >> > instead of a separate style guide for regular code, I propose an
> >> > exception for this one problem rule.
> >> >
> >> > Ultimately this comes down to the question - should PEP8 push regular,
> >> > not-Python-implementation code to use is for singletons in cases where
> >> > == works perfectly? Seeing how effortless it is for programmers to use
> >> > == as their first choice, I think PEP8 should allow that practice.
> >> >
> >> > Best,
> >> >
> >> > Nick
> >> > _______________________________________________
> >> > Python-ideas mailing list -- python-ideas@python.org
> >> > To unsubscribe send an email to python-ideas-le...@python.org
> >> > https://mail.python.org/mailman3/lists/python-ideas.python.org/
> >> > Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/JWLKBT2YYDGFS76Z37FZJNZPEDVXOLCW/
> >> > Code of Conduct: http://python.org/psf/codeofconduct/
>
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/YBEVAKWJBZR3MCZHM5RAFKVYACIIZQ4B/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to