Reputation: 31
After reading this and this, I still cannot understand the following behaviour:
a = 1000
b = 1000
print (a == b)
print (a is b)
print (f"id(a) = {id(a)} \nid(b) = {id(b)}")
As expected I get
True
True
id(a) = 2806705928816
id(b) = 2806705928816
But when i try to do something like this:
a = 1000
b = 1000 + a - a
print (a == b)
print (a is b)
print (f"id(a) = {id(a)} \nid(b) = {id(b)}")
I got False
in expression a is b
True
False
id(a) = 3030783801968
id(b) = 3030783802064
Why does a variable behave differently when assigning the result of an expression over a integer and an expression with other variables to it? Although mathematically this gives the same integer.
Upvotes: 2
Views: 102
Reputation: 3178
You already have a few accurate answers. Here I am giving a "back to basics" answer.
==
?Python ==
means is the value on the left the same as the value on the right.
sum([5, 7]) == (48 * 3)**0.5
is True
. It requires several evaluation steps to make each expression reach the value of 12
. Even then, the integer 12
is being compared to the float 12.0
, so a final conversion of the integer to a float is necessary.
The key takeaway: each expression is evaluated and the resulting values are compared. If they are equal, then the expression is true.
is
?Python is
, on the other hand, means is the name on the left pointing to the same object as the name on the right.
a = 3.14159
b = a
a is b
is True
. a
has been assigned to the value 3.14159
. But more to the point, there is a block of memory holding an object, which in this case is the float 3.14159. a
points to that object / block of memory. b
points to a
, which means that it points to that same block of memory.
You can very easily test this: create two "names" that simply point to a number, and compare them using is
, and they will not match:
>>> a = 1239481203948
>>> b = 1239481203948
>>> a is b
False
This is false because we now have two different locations in memory / objects pointing to each of them:
>>> id(a)
140402381635344
>>> id(b)
140402391174416
(On your machine, you will get a different set of id
s.)
So, in effect, you have "wasted" space because you have two objects taking up space for the same information.
If you play around with this on your own, you will find tons of exceptions to what I wrote, and confuse yourself. Here are just a few:
>>> a = 157
>>> b = 157
>>> a is b
True
What?? Why is this true? To optimize Python, the "most common numbers" have been optimized. I may be wrong, but I recall that there is designated space in memory for the most common numbers. And those are the first few hundred integers, and a few others.
But there are other optimizations, too:
>>> a = None
>>> b = None
>>> a is b
True
>>> a = True
>>> b = True
>>> a is b
True
These are all still following the same rule as I stated earlier: the reason why is
evaluates to True
is because a
and b
are both pointing to the same location in memory / object.
This happens in these odd cases because of optimizations in Python. But generically speaking, the only way to ensure is
evaluates to True
is if a name is assigned to an object that already has a name, like when we wrote:
>>> a = 3.14159
>>> b = a
>>> a is b
True
instead of writing
>>> a = 3.14159
>>> b = 3.14159
>>> a is b
False
Upvotes: 1
Reputation: 2430
When you do something like :
(case-1)
a = 1000
b = a
or (case-2)
a = 1000
b = 1000
Python is smart enough to know before hand that even after execution you won't need new memory.
So, python just before execution makes b
an alias of a
in the first case.
The second case is bit different.
Python is a true object oriented language, the literal 1000
is treated as an object. (Intuitively you can think as 1000 to be name of a const object).
So in second case a
and b
are technically, both becoming alias
of 1000
Now in your example:
a = 1000
b = 1000 + a - a
print (a == b)
print (a is b)
while assignment of b
, python doesn't know before hand what is going to be the value of a
. When I say before-hand I mean before any form of calculation being started. So python reserves a new memory location for b
and then saves the output of the operation in this new memory location.
It is also worth noting this:
4-1 is 3
True
In this case, python doesn't saves this line with 4-1
but processes it before compilation to be 3
, for runtime optimisation.
Upvotes: 3
Reputation: 646
Python executes a statement by evaluating its expressions to values one by one, then performing some operation on those values.
Source: https://courses.cs.washington.edu/courses/cse140/13wi/eval_rules.pdf
Basically b = 1000 + a - a is not being done in one go, but in multiple evaluations and python stores the results for b at each evaluation in a different memory location than a. At this point a and b are different objects.
use == for equality checks.
use "is" to check if objects are same (variables are referencing same memory location).
Upvotes: 0
Reputation: 1486
the difference is in the reference to location. '==' checks for equality in terms of data type and value however, 'is; reference the location of variable in memory.
is will return false for the below
id(a) = 3030783801968 <----
id(b) = 3030783802064 <----
is will return true for the below
id(a) = 2806705928816 <----
id(b) = 2806705928816 <----
Upvotes: 0