> 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 <nick@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 <bussonniermatthias@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 <nick@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-leave@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/