Why is () is ()
true, yet (0,) is (0,)
is false?
I thought they would be the same object. However, I'm apparently missing something.
is
tests to see if both sides of the statement share the same memory address. It's basically a shorthand for id(a) == id(b)
>>> print id(()), id(())
30085168 30085168
>>> print id((0,)), id((0,))
38560624 38676432
>>>
As ()
happens fairly frequently, it is actually treated as a singleton by the Python Interpreter (just like integers from 0 to 255, empty strings, empty lists, etc.). When comparing (0, )
to (0, )
to the interpreter they are actually different variables in memory. If they were mutable, you could modify the first, and the second wouldn't change, hence they are not the same (a is not b
).
[]
to create a new list! Also, be careful with using id
on temporary objects like that; on my system entering (id([]), id([]))
into the REPL gives (48511432L, 48511432L)
, but this doesn't mean they were the same object; it's just that the first list was discarded as garbage after being id
ed, then the second was allocated into this convenient empty-list-sized hole in memory that just freed up. id
values are potentially meaningless unless you ensure that the object lives longer than the id
value - Ben 2012-04-04 06:17
[] is []
suffer from the same temporary object issue (i.e., can it evaluate as True
simply because memory was reused)? I am guessing not, but not sure how this is prevented - max 2012-04-23 06:25
is
testing is fine. The reason is that is
tests the objects directly, which means they must both be alive at the same time in order for you to pass them to is
, so there's no way they can accidentally have the same memory address if they're different objects. Comparing id
results separates things out into multiple stages, creating the possibility that the first object is deallocated after you take its id
but before the second object is allocated, which creates the possibility that two different objects get allocated at the same address and have the same id
- Ben 2012-04-23 21:25
is
tests for identity, not equality. That means Python simply compares the memory address a object resides in. is basically answers the question "Do I have two names for the same object?"
Usually Python writes each tuple into a different memory location,
interning will mostly happens only for string literals.
As Dougal says in his comment, is
tests that the two things you are comparing are the in the same place in memory. For things like numbers, strings, booleans and the empty tuple, Python reuses objects by default (interning) so is
will often produce the same behaviour as ==
. This also means that you can get some performance gains by comparing memory pointers rather than more complex datatypes like strings.
For other things such as the tuple in your case (even though they are immutable), or lists and even the empty list []
, Python will create a new object in a different memory location and is
won't work the same way as ==
If you're trying to compare the two tuples by value, ==
would be the better comparison.
is
becomes unpredictable for these objects. So while using is
to compare strings can be more efficient, it runs the risk of introducing subtle bugs to your code unless you use it only in controlled places where you know the behaviour of your program can't run into this issue. Generally immutable objects should always be compared with ==
rather than is
- Ben 2012-04-04 06:05
a is b or a == b
also work? Though, the second comparison may negate the performance gained - rectangletangle 2012-04-04 06:18
a
usually isn't b
, then you're just wasting work most of the time. Using multiple Python-level operations to save a short C loop also doesn't sound that likely to be a huge payoff, unless comparing huge a string to itself is common. I just use ==
when what I'm testing is semantically equality and is
when what I'm testing is semantically identity. In theory I could then go back and replace some of these if I found string comparison to be a significant bottleneck in a program that was too slow, but this has never happened to me - Ben 2012-04-04 06:23
is
means that they're the same object in memory. Apparently CPython only has one copy of the empty tuple but makes new ones for tuples with contents - Dougal 2012-04-04 04:36