Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
965 views
in Technique[技术] by (71.8m points)

python - Why isn't "is" comparison used in place of "==" for primitive types?

When I'm using Pytest for Python formatting, it complains about doing something like:

>>> assert some_function_ret_val() == True
E712 comparison to True should be 'if cond is True:' or 'if cond:'

and wants:

assert some_function_ret_val() is True

I know there can only be one copy of True/False/None, but I thought all primitives are immutable types.

Under what circumstances would "==" and "is" comparison be different for primitive types??

Otherwise, why has "==" become the norm in comparison tasks?

I found this stackoverflow post that talks about comparison with non-primitive types, but I can't seem to find a reason for why "is" comparison might be dangerous with primitive types. Comparison with boolean numpy arrays VS PEP8 E712

If it's just convention, I would think that "is" is more legible than "==", but I feel like there could be some crazy edge cases where maybe there are more than one copy of a primitive type.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Python does not have primitive types. Everything in Python is an object.

Generally, the only place you should use is are on language-guaranteed singletons, like True, False, and None or, say for debugging purposes, you actually want to check object identity.

In every other case, you will be relying on implementation details and implementation-specific optimizations if you use is to mean equality (e.g. the peep-hole optimizer and string interning). The equality operator is == and should be used in those cases. While often, the Python interpreter will optimize immutable types, you should still not rely on identity when you mean equality, because mostly that is not a language guarantee.

As an example, while on CPython 3.7, you can "safely" be tempted choose to use is to compare small integers because they are cached, this is an implementation detail that should not be relied upon. This is free to change in Python 3.9 or whenever. Also, see the comment by @user2357112 about how it isn't even necessarily safe for the small integers that are cached! To reiterate: it is not a language guarantee - it is a side-effect of how it was implemented.

And also, again, it only applies to small integers, [-5, 256] so:

>>> def add(a, b): return a + b
...
>>> 16 is add(8, 8)
True
>>> 1000 is add(500, 500)
False

Note, I put the actual addition in a function, the interpreter frequently optimizes immutable literals and arithmetic expressions:

>>> 1000 is (500 + 500)
True

But it should be obvious now why you cannot rely on that.

Another example where it is appropriate to use is for "equalityish" comparisons is to compare enum types, which are guaranteed singletons:

import enum
class Color(enum.Enum):
    RED = 1
    BLUE = 2

RED = Color.RED
BLUE = Color.BLUE

print(Color(1) is RED)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...