Fernando’s posterous

article repository; random thoughts 
« Back to blog

Python bizarre integer equality

Of course it works perfectly with ==, but that's not "object equality" in Python anyway:
 
(From http://distilledb.com/blog/archives/date/2009/06/18/python-gotcha-integer-equality.page )
 
----------------
 
 
Python gotcha: Bizarre integer equality
 
John
Thursday, June 18, 2009 @ 20:00
 
Summary Python implementations can throw you a curveball when comparing integer identity.
 
In Python, everything is an object. These semantics are predictable for the most part -- until they aren't. Here's a short but confusing snippet of Python 3 code, running from Ubuntu 9.04. Can you surmise why this inconsistency happens?
 
 >>> a = 500
 >>> b = 500
 >>> a is b
False
 
 >>> c = 200
 >>> d = 200
 >>> c is d
True
 
In Python, is tests for identity, not equality. x is y if and only if x and y reference the same thing. Although a and b have the same value, they are distinct objects, and so comparing the two yields False, as one might expect.
 
But then we're confronted with the second case. It's precisely identical to the first, just with a different assigned value. Yet it produces the opposite result. How can this be?
 
The key to this puzzle lies in a peculiar implementation detail of CPython, the de facto Python implementation. As we said earlier, in Python, everything is an object, even literals. Logically, that means that two different instances should be distinct from each other, as in the first case above.
 
But in CPython, when you create an integer literal in the range [-5, ..., 256], it's actually cached for performance reasons. Further references to the same literal are identical references to the existing literal, not new references. Thus c and d refer to the same cached instance, and the result is True.
 
Because of another implementation detail, two literals with the same value that are in the same compilation unit will reference the same object. Comparing literals directly results in True in both cases, as we see here:
 
 >>> 200 is 200
True
 
 >>> 500 is 500
True
 
More importantly, however, this illustrates the danger when is is mistakenly used to compare value equality instead of reference equality. Had you used == instead, the results are precisely what you'd expect:
 
 >>> a = 500
 >>> b = 500
 >>> a == b
True
 
 >>> c = 200
 >>> d = 200
 >>> c == d
True

Comments (0)

Leave a comment...

 
To leave a comment on this posterous, please login by clicking one of the following.
Posterous-login     Connect     twitter