You already have a few accurate answers. Here I am giving a "back to basics" answer.
What is ==
?
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.
What is 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.
But wait, there's more
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