"is" operator result: What is happening? [duplicate] - python

This question already has answers here:
Understanding the "is" operator [duplicate]
(11 answers)
Closed 3 years ago.
I was quite surprised when
[] is not []
evaluated to True.
What is happening in this code? What really not and is statements are doing?

a is not b is a special operator which is equivalent to not a is b.
The operator a is b returns True if a and b are bound to the same object, otherwise False. When you create two empty lists you get two different objects, so is returns False (and therefore is not returns True).

is is the identity comparison.
== is the equality comparison.
Your statement is making two different lists and checking if they are the same instance, which they are not. If you use == it will return true and because they are both empty lists.

The best way to describe WHY that happens is this:
Here is your example
>>> x = []
>>> y = []
>>> print(x is y)
... False
x and y are actually two different lists, so if you add something to x, it does not appear in y
>>> x.append(1)
>>> print(x)
... [1]
>>> print(y)
... []
So how do we make (x is y) evaluate true?
>>> x = []
>>> y = x
>>> print(x is y)
... True
>>> x.append(10)
>>> print(x)
... [10]
>>> print(y)
... [10]
>>> print(x is y)
... True
if you want to see if two lists have the same contents...
>>> x = []
>>> y = []
>>> print(x == y)
... True
>>> x.append(21)
>>> print(x)
... [21]
>>> print(y)
... []
>>> print(x == y)
... False
>>> y = [21]
>>> print(x == y)
... True

is means is same instance. It evaluates to true if the variables on either side of the operator point to the same object and false otherwise.
Reference, near the bottom.

is checks for identity. [] and [] are two different (but equivalent) lists. If you want to check if both the lists are empty you can use their truth value (false for empty strings, collections, and zeros).
if not ([] and []):
print 'Spanish Inquisition'
the only time that is is guaranteed to return True is for singletons such as None. Like the Highlander, there can be only one instance of None in your program - every time you return None it's the very same "thing" as the none referred to if you type print None.
[], OTOH, is not guaranteed to be anything except an empty list and evaluate to False in a boolean context.

I know I am posting to a pretty old post. however, this might help someone stumble upon this like me.
"is" checks, whether a memory address is same or not, while "==" check if the value is same or not. Would be much clear from the following example
let's first talk about immutable objects, as it's easy to understand
# could be any immutable object
immutable_a = 10
immutable_b = 10
# prints address of a and b variable
print "address of a is %s" % id(immutable_a)
print "address of a is %s" % id(immutable_b)
# as both addresses is same, following shall be true
print immutable_a is immutable_b
# as the values are also same, following shall be true as well
print immutable_a == immutable_b
now let's talk about mutable objects
# could be any mutable object
mutable_a = [10]
mutable_b = [10]
# prints address of a and b variable
print "address of mutable_a is %s" % id(mutable_a)
print "address of mutable_b is %s" % id(mutable_b)
# as addresses are not same, following shall be false
print mutable_a is mutable_b
# as the values are same, following shall be true
print mutable_a == mutable_b

#Jiaaro is right. Using is with immutable data types is dangerous because it is not predictable because of Pythons interpreter optimization.
See this example:
10 * "a" is 10 * "a" # True
100 * "a" is 100 * "a" # False
In the second line it is faster to create a new object with a new id for the interpreter. So use the is operator only with mutable types.

Related

why is id(1) is id(1) returning False?

I know the is operator compares the id of the two, not the value
However when you evaluate id(1) and id(1), the object (which is an int) is equal to one another.
So why is it returning false?
id(1) # 27533656
id(1) is id(1) # False
type(id(1)) # int
so then, technically, deduce it to
id(1) is id(1)
27533656 is 27533656 # has to be True!
is checks for object identity whereas == checks object equality. The difference can be subtle, but is most easy to see when dealing with mutable objects like lists:
x = [1, 2, 3]
y = x[:] # copy, not the same list
x is y # False
x == y # True
If I add something to x, y won't see it:
x.append(4)
x == y # now False since they have diverged.
But, if I alias x and append to it, the alias will also see the changes:
z = x # alias `z` to `x`
x.append(5)
x == z # True
And the reason for this is because z is x.
z is x # True
In this case, the id of 1 is consistent because CPython1 caches small integers for efficiency (so the object literal 1 is always the same object -- and therefore the same Id). However, the return value of id can actually be a different instances of int that have equivalent values.
1This is a well known implementation detail for CPython. Other implementations (and future versions) are free behave differently so do not rely on this behaviour.
You're slightly misinterpreting what the is syntax does.
What you are doing with that bit of code is roughly:
id(id(1)) == id(id(1))
Because the value returned by the id function is not static and not guaranteed to be the same identity, they will most likely be different identities.
As proof, when I put those into a print statement I get:
print id(id(1)) # 4327028
print id(id(1)) # 4326968
Which are obviously not the same.
If you were to change the code to:
if 1 is 1: # basically in this case id(1) == id(1)
print "success"
You would find that the values are indeed the same id.
As noted in the comments. The x is x and id(x) == id(x) methods of determining equivalence are not always the same for all literal types.
In the specific case of this question they may be treated as equal.

Why does this str strict comparison fail in Python? [duplicate]

This question already has answers here:
Why does comparing strings using either '==' or 'is' sometimes produce a different result?
(15 answers)
Closed 8 years ago.
I have this code in a decorator:
is_local_valid = ['system_id', 'server_id', 'sensor_id']
local_params = [x for x in is_local_valid if x in kwargs.keys() and kwargs[x].lower() is 'local'] + [y for y in args if y.lower() is 'local']
if local_params == []:
raise AssertionError("Tried to access the database from a non connected profile")
I noticed that the is infix operator for comparing two strings returns False in this case, even when kwargs[x].lower() equals to local. The == operator does return True, though. Both are str, of course.
Any clue on what's going on?
The operators is and is not test for object identity:
x is y is true if and only if x and y are the same object. x is not y yields the inverse truth value.
>>> id('local')
42745112
>>> a = {1: 'locAl'}
>>> id(a[1].lower())
53363408
They are not the same object
a is b determines whether two names a and b reference the same object (i.e. id(a) == id(b)). a == b determines whether they have equal values. It is rarely a good idea to compare strings with is; use == instead:
>>> "".join("hello")
'hello'
>>> "hello" is "".join("hello")
False
>>> "hello" == "".join("hello")
True
The only general case for comparison with is would be for None, e.g.:
if a is None:

How does python evaluate "is" expressions? [duplicate]

This question already has answers here:
"is" operator behaves unexpectedly with integers
(11 answers)
Closed 9 years ago.
Erratic behavior of "is" expressions in python.
>>> 258 -1 is 257
False
And
>>> 258 -1 == 257
True
How is python evaluating "is" expression ? and why does it show it as false , eventhough it is true ?
Why is it happening only to certain set of numbers ?
2 - 1 is 1
True
works perfectly fine.
is is used for identity check, to check if both variables point to the same object,
while == is used for checking values.
From the docs:
The operators is and is not test for object identity: x is y is true
if and only if x and y are the same object. x is not y yields the
inverse truth value.
>>> id(1000-1) == id(999)
False
""" What is id?
id(object) -> integer
Return the identity of an object. This is guaranteed to be unique among
simultaneously existing objects. (Hint: it's the object's memory address.)
"""
>>> 1000-1 is 999
False
>>> 1000-1 == 999
True
>>> x = [1]
>>> y = x #now y and x both point to the same object
>>> y is x
True
>>> id(y) == id(x)
True
>>> x = [1]
>>> y = [1]
>>> x == y
True
>>> x is y
False
>>> id(x),id(y) #different IDs
(161420364, 161420012)
But some small integers(-5 to 256) and small strings are cached by Python: Why (0-6) is -6 = False?
#small strings
>>> x = "foo"
>>> y = "foo"
>>> x is y
True
>>> x == y
True
#huge string
>>> x = "foo"*1000
>>> y = "foo"*1000
>>> x is y
False
>>> x==y
True
is compares object identity and yields True only if both sides are the same object. For performance reasons, Python maintains a "cache" of small integers and reuses them, so all int(1) objects are the same object. In CPython, cached integers range from -5 to 255, but this is an implementation detail, so you should not rely on it. If you want to compare equality, use ==, not is.
The is operator checks for object identity: the object created by calling 258-1 is NOT the same object as the one created by 257. The == operator checks if the values of the compared objects are the same.
Try using help('is').
The Python is operator checks for object identity, not object value. The two integers must refer to the same actual object internally for is to return true.
This will return true for "small" integers due to an internal cache maintained by Python, but two numbers with the same value will not return true if compared with is in general.

How does "is" work in python?

Can please someone explain how one may use 'is' in an 'if' condition. I am working with the fractions module, and I'm having some trouble:
>>> Fraction(0, 1) is 0
False
>>> float(Fraction(0, 1))
0.0
>>> float(Fraction(0,1)) is 0.0
False
The only thing I found to work is:
>>> F = Fraction(a,b)
>>> if F >= 0:
... if F(0, 1) <= 0:
... ...
Is there a way to use 'is' here? Thanks.
The is operator in python is used to check if two variables are pointing to the very same object and is not meant to be used to check about numeric equality. You should use == for that instead.
For example consider that
(1000 + 1000) is (1000 + 1000)
returns False.
From the documentation:
The operators is and is not test for object identity: x is y is true if and only if x and y are the same object. x is not y yields the inverse truth value.
What you want here is ==, to test whether two objects are equal or equivalent by comparing the values and not the identities.
A trivial example (in CPython that may differ in other implementations):
>>> 1 + 2 == 3.0
True
>>> 1 + 2 is 3.0
False
>>> 1 + 2 is 3
True
>>> id(1 + 2)
4298185512
>>> id(3.0)
4298194656
>>> id(3)
4298185512
is checks for object identity. It returns true if two names refer to the same object. One typical usecase is to check if a name refers to None:
if foo is None:
# do stuff
a is b is equivalent to id(a) == id(b)
Quote from http://docs.python.org/library/operator.html:
operator.is_(a, b) Return a is b.
Tests object identity.

and / or operators return value [duplicate]

This question already has answers here:
How do "and" and "or" act with non-boolean values?
(8 answers)
Closed 4 years ago.
I was watching a 2007 video on Advanced Python or Understanding Python, and at 18'27" the speaker claims "As some may know in Python and and or return one of the two values, whereas not returns always a boolean." When has this been the case?
As far as I can tell, and and or return booleans, too.
The and and or operators do return one of their operands, not a pure boolean value like True or False:
>>> 0 or 42
42
>>> 0 and 42
0
Whereas not always returns a pure boolean value:
>>> not 0
True
>>> not 42
False
See this table from the standard library reference in the Python docs:
from Python docs:
The operator not yields True if its argument is false, False otherwise.
The expression x and y first evaluates x; if x is false, its value is returned; otherwise, y is evaluated and the resulting value is returned.
The expression x or y first evaluates x; if x is true, its value is returned; otherwise, y is evaluated and the resulting value is returned.
Python's or operator returns the first Truth-y value, or the last value, and stops. This is very useful for common programming assignments that need fallback values.
Like this simple one:
print my_list or "no values"
This will print my_list, if it has anything in it. Otherwise, it will print no values (if list is empty, or it is None...).
A simple example:
>>> my_list = []
>>> print my_list or 'no values'
no values
>>> my_list.append(1)
>>> print my_list or 'no values'
[1]
The compliment by using and, which returns the first False-y value, or the last value, and stops, is used when you want a guard rather than a fallback.
Like this one:
my_list and my_list.pop()
This is useful since you can't use list.pop on None, or [], which are common prior values to lists.
A simple example:
>>> my_list = None
>>> print my_list and my_list.pop()
None
>>> my_list = [1]
>>> print my_list and my_list.pop()
1
In both cases non-boolean values were returned and no exceptions were raised.
Need to add some points to the #Frédéric 's answer.
do return one of their operands???
It is True but that is not the logic behind this. In python a number except 0 is considered as True and number 0 is considered as False.
(0 and 42 -> False and True) = False.
That's why it returns 0.
(0 or 42-> false or True) = 42
In that case the statement will be True because of the operand 42. so python returns the operand which causes the statement to be true, in that case.

Categories