So the is
keyword returns true only if the two arguments point to the same object. My question is related to the snippet below.
This snippet
number = None
if number is None:
print("PEP 8 Style Guide prefers this pattern")
Outputs
>>PEP 8 Style Guide prefers this pattern
Does this mean when I assign number = None
then it is only by reference, because is
checks if it is the same object. I'm so confused why this happens?? Am I wrong?? Why was this design choice made?
This is because of two reasons.
In the following code
x = object()
y = x
print(x is y) # True
print(id(x)) # 139957673835552
print(id(y)) # 139957673835552
Calling object()
creates a new structure in memory, whose unique identifier can be accessed with the id()
function.
You can imagine x
and y
being arrows pointing to the same object, and this is why their underlying identifier is the same in both cases.
As such, when assigning None
to a variable, you're just saying "number
is an alias, an arrow pointing to the object returned by writing None
". You can check that
number = None
print(id(None), id(number))
will give you the same identifier two times. But wait! What if you do it for a big number like 100000
?
number = 100000
print(id(100000), id(number)) # Different values!
This means that the same literal, written two times, can return different objects, bringing up the next reason.
Note that no matter how many times you get the None
identifier, you get the same one.
print(id(None)) # 139957682420224
print(id(None)) # 139957682420224
print(id(None)) # 139957682420224
This is because writing None
doesn't create a new object, as in the first example, because the language specification guarantees that there's only one possible object of NoneType
in memory. In other words, there's only one possible object returned by writing None
, making comparisons with is
work as expected. This is a good design choice: There's only one canonical way for saying that a variable (an arrow) points to nothingness.
In fact, using is
is encouraged as the Pythonic way of checking that a variable is None
.
You can also get the class of the object by writing
NoneType = type(None)
and notice how
NoneType() is None
is true.
Note: The uniqueness property is also satisfied by other literals, particularly small numbers, for performance reasons.