My expectation was that the result should be True as I thought immutable numeric objects (or a tuple of them) have just one instance.
That expectation is questionable - there's no such thing guaranteed by the Python language.
is
is a quite tricky operator because you really need to know when it's appropriate to use it.
For example:
>>> 5 / 2 is 2.5
>>> (1, 2, 3) is (1, 2, 3)
These are not appropriate uses of is
in the general case. They may be appropriate if you want to check what line/function optimizations (interning) Python is doing but I guess that wasn't the desired use-case here.
is
should only be used if you want to compare to constants (that are guaranteed to only have one instance)! The guaranteed built-in constants are:
None
NotImplemented
Ellipsis
(also known as ...
)
True
False
__debug__
Or your own constant-like instances:
_sentinel = object()
def func(a=_sentinel):
return a is _sentinel
Or when you explicitly assign variables to a new name:
a = b
a is b # <- that's expected to be True
Does anyone know what changes have been made which explains this new behaviour?
Probably the peep-hole optimizer now optimizes more cases (tuples and mathematical expressions). For example "AST-level Constant folding" (https://bugs.python.org/issue29469) has been added in CPython 3.7 (I intentionally wrote CPython here because it's nothing that has been added to the Python 3.7 language specification).