Python 3.14.0a0 (heads/main:b02301fa5a5, Sep 14 2024, 10:15:21) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> def f(x, y):
... return x + y
...
>>> f((1,2),(2,)) is f((1,2),(2,))
False
>>> f(2,3) is 5
<python-input-2>:1: SyntaxWarning: "is" with 'int' literal. Did you mean "=="?
f(2,3) is 5
True
Why should not two hashable object with the same value be equal when they are passed through a function?
They are equal but not necessarily identical (ie the same object).
Having them being identical is an implementation detail and you shouldnât rely on that (as the warning says).
tl;dr is checks identity. == checks equality. If a is b then a == b but the reverse does not always hold.
>>> a = [1, 2]
>>> b = [1, 2]
>>> a == b
True
>>> a is b
False
>>> c = a
>>> c is a
True
The long version:
Python variables are references to objects, not the objects themselves. is looks at the reference to determine if they are the same. == looks at the values being referenced to determine if they are equal. @trey did a very nice video on this.
Itâs not quite that Python assumes that identity implies equality, but that for those sorts of comparisons, the actual check is âidentical or equalâ.
Sequences compare lexicographically using comparison of corresponding elements. The built-in containers typically assume identical objects are equal to themselves.
The is operators tests if object are identical. Per docs: The operators is and is not test for an objectâs identity: x is y is true if and only if x and y are the same object. An Objectâs identity is determined using the id() function. x is not y yields the inverse truth value.
Itâs easy to see, that in you case objects arenât identical:
Funny I find it easier to think of it as âsame pointerâ vs âsame valueâ.
Regardless, itâs useful to understand under which circumstances you can expect a is b and which operations change the underlying value of a rather than constructing a new value, because such operations would also change the value of other variables with the same pointer.
Be careful with that as the validity of id return value depends on the objectâs lifetime: two different objects can share a same id if they do not exist in memory at the same time, but they are not identical.
Yes, but you canât compare such objects with is operator:)
Idâs arenât determined by objectâs content. Same (wrt equality) objects can have different id (in CPython isât just address of the object in memory) within one session:
>>> [1, 2, 3] # (1)
[1, 2, 3]
>>> id(_)
140433683777216
>>> [1, 2, 3] # (2); at this point (1) might be even garbage-collected
[1, 2, 3]
>>> id(_)
140433681649600
>>> [1, 2, 3] is [1, 2, 3]
False