For some types in Python, the is
operator seems to be equivalent to the ==
operator. For example:
>>> 1 is 1
True
>>> "a spoon" is "a spoon"
True
>>> (1 == 1) is (2 == 2)
True
However, this is not always the case:
>>> [] == []
True
>>> [] is []
False
This makes sense for mutable types such as lists. However, immutable types such as tuples seem to display the same behavior:
>>> (1, 2) == (1, 2)
True
>>> (1, 2) is (1, 2)
False
This raises several questions:
==
/ is
equivalence related to immutability? Update:
If assignment is always by reference, why doesn't the following print 2
?:
>>> a = 1
>>> b = a
>>> a = 2
>>> b
1
Why isn't this equivalent to the following C snippet:
int a = 1;
int *b = &a;
a = 2;
printf("%d\n", *b);
Apologies for the newbness of this question, but I am a Python novice and feel that it is important to understand this. Is there any reading you would recommend to understand these sort of issues?
The is
operator tests if two objects are physically the same, that means if they have the same address in memory. This can also be tested using the id()
function:
>>> a = 1
>>> b = 1
>>> a is b
True
>>> id(a) == id(b)
True
The ==
operator on the other hand, tests for semantical equality. This can also be overridden by custom classes by implementing the __eq__()
function. Semantically, two different lists are equal if their elements are all equal, but physically they will be different objects.
Immutable types like strings and tuples might be pooled by the Python implementation, so that two literal string objects are in fact physically identical. But this does not mean that you can always use is
to compare those types, as demonstrated in the following example:
>>> "foobar" is "foobar" # The interpreter knows that the string literals are
True # equal and creates only one shared object.
>>> a = "foobar"
>>> b = "foobar"
>>> a is b # "foobar" comes from the pool, so it is still the same object.
True
>>> b = "foo" # Here, we construct another string "foobar" dynamically that is
>>> b += "bar" # physically not the same as the pooled "foobar".
>>> a == b
True
>>> a is b
False
Assignments in Python always bind the reference to an object to a variable name and never implies a copy.
UPDATE
Analogous to C, think of Python variables always being pointers:
>>> a = 1
>>> b = a
>>> a = 2
>>> b
1
Roughly equivalent to:
const int ONE = 1;
const int TWO = 2;
int *a = &ONE;
int *b = a; /* b points to 1 */
a = &TWO; /* a points to 2, b still points to 1 */
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With