8.1. Why 256 Is 256 but 257 Is Not 257¶
The == operator compares two objects for equal value, but the is operator compares them for equal identity. Although the integer value 42 and the float value 42.0 have the same value, they’re two different objects held in separate places in the computer’s memory. You can confirm this by check- ing their different IDs using the id() function:
>>> a = 42
>>> b = 42.0
>>> a == b
True
>>> a is b
False
>>> id(a), id(b)
(140246631423568, 140246592683504)
When Python creates a new integer object and stores it in memory, that object creation takes very little time. As a tiny optimization, CPython (the Python interpreter available for download at https://python.org) creates integer objects for -5 to 256 at the start of every program. These integers are called preallocated integers, and CPython automatically creates objects for them because they’re fairly common: a program is more likely to use the integer 0 or 2 than, say, 1729 . When creating a new integer object in memory, CPython first checks whether it’s between -5 and 256 . If so, CPython saves time by simply returning the existing integer object instead of creating a new one. This behavior also saves memory by not storing duplicate small integers, as illustrated in Figure 9-1.

Figure 9-1: Python saves memory by using multiple references to a single integer object (left) instead of separate, duplicate integer objects for each reference (right).
Because of this optimization, certain contrived situations can produce bizarre results. To see an example of one, enter the following into the inter- active shell:
>>> a=256
>>> b=256
>>> a is b
True
>>> c=257
>>> d=257
>>> c is d
False
All 256 objects are really the same object, so the is operator for a and b returns True 1. But Python created separate 257 objects for c and d , which is why the is operator returns False 2.
The expression 257 is 257 evaluates to True , but CPython reuses the integer object made for identical literals in the same statement:
>>> 257 is 257
<>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
<>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
<ipython-input-6-dd70d8dec340>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
257 is 257
True
Of course, real-world programs usually only use an integer’s value, not its identity. They would never use the is operator to compare integers, floats, strings, bools, or values of other simple data types. One exception occurs when you use is None instead of == None , as explained in “Use is to Compare with None Instead of ==” on page 96. Otherwise, you’ll rarely run into this problem.