I was just reading about the 'unexpected result of is operator' which happens because Python cache numbers between -5 and 256.
This was discussed here: "is" operator behaves unexpectedly with integers
and here: "is" and "id" in Python 3.5
When I run one of the examples given there, I get different results between Python Idle and Python IDE (I'm using Jetbrains Pycharm professional edition - 5.0.4).
When using Python IDLE this is the result:
a = 1000
b = 1000
print (a is b) # prints False
when using Pycharm 5.0.4 this is the result:
a = 1000
b = 1000
print (a is b) # prints True
how could this be? I've rechecked, and my project's Python-Interpreter is exactly the same in both cases (both are Python 3.5.1). Not sure if this is something I've done wrong, and I was hoping if someone could explain this.
Edit:
I know 'a' is 'b' == true iff id(a) == id(b), and that you can check it like some of you mentioned in the comments. Perhaps I should have been more clear, what I don't understand is how could it be that an IDE has different behavior? I thought (and please, correct me, as it seems I'm wrong) that an IDE is just a user-friendly environment that uses external compilers / interpreters, and this is why these are independent of those IDE's (for instance, pycharm supports not only Python, and I could run Eclipse with C compiler, or Java etc. (all of which are not parts of the IDE).
Thanks, Alon.
This is because of how LOAD_CONST
byte code works:
Pushes
co_consts[consti]
onto the stack.
Since integers are stored as constants then assignments to the same integer in the same context will yield the exact same result, we can see that the arguement to LOAD_CONST
is 0
for both a and b:
>>> import dis
>>> dis.dis("a = 1000 ; b = 1000")
1 0 LOAD_CONST 0 (1000)
3 STORE_NAME 0 (a)
6 LOAD_CONST 0 (1000)
9 STORE_NAME 1 (b)
12 LOAD_CONST 1 (None)
15 RETURN_VALUE
# ^ this is the argument
where as in an interactive session each command is compiled separately (so that they can be executed separately) so the constants will be different:
>>> code1 = compile("a = 1000","<dummy file>","exec")
>>> code2 = compile("a = 1000","<dummy file>","exec")
>>> code1.co_consts, code2.co_consts
((1000, None), (1000, None))
>>> code1.co_consts[0] is code2.co_consts[0]
False
Similarly the constant in a function will always be the same but it will be different to the constant in other functions:
def f():
return 1000
def g():
return 1000 #different code object!!
#these all work
assert f() is f()
assert g() is g()
assert f() is not g()
assert f() is not 1000 and g() is not 1000
Also note that as @AniMenon has pointed out the numbers from -5 to 256 are singletons for optimization so the same will not hold true for numbers in that range.
From the documentation for the is operator:
The operators
is
andis not
test for object identity:x is y
is true if and only if x and y are the same object.
Now lets check IDLE:
>>> a = 1000
>>> b = 1000
>>> print ( a is b )
False
>>>
>>>
>>> id(a)
35334812
>>> id(b)
35334800
PyCharm:
>>> a = 1000
b = 1000
print (a is b)
True
>>> id(a)
36079236
>>> id(b)
36079236
In PyCharm both a
and b
are the same objects when in IDLE they are not.
Now what's instersting in PyCharm, that if you entering your code line by line, like in IDLE, you'll get the same results as in IDLE:
>>> a = 1000
>>> b = 1000
>>> print (a is b)
False
My guess, that
>>> a = 1000
b = 1000
is optimized to:
>>> a = b = 1000
>>> print (a is b)
True
So that's why you got same object for a
and b
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