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

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:

Related

The is keyword in python [duplicate]

This question already has answers here:
Why does comparing strings using either '==' or 'is' sometimes produce a different result?
(15 answers)
"is" operator behaves unexpectedly with integers
(11 answers)
Is there a difference between "==" and "is"?
(13 answers)
Is there any difference between "foo is None" and "foo == None"?
(12 answers)
Closed 2 years ago.
The is keyword in python is described like that:
is is used in Python for testing object identity. While the == operator is used to test if two variables are equal or not, is is used to test if the two variables refer to the same object.
It returns True if the objects are identical and False if not.
>>> True is True
True
>>> False is False
True
>>> None is None
True
We know that there is only one instance of True, False and None in Python, so they are identical.
>>> [] == []
True
>>> [] is []
False
>>> {} == {}
True
>>> {} is {}
False
An empty list or dictionary is equal to another empty one. But they are not identical objects as they are located separately in memory. This is because list and dictionary are mutable (value can be changed).
>>> '' == ''
True
>>> '' is ''
True
>>> () == ()
True
>>> () is ()
True
Unlike list and dictionary, string and tuple are immutable (value cannot be altered once defined). Hence, two equal string or tuple are identical as well. They refer to the same memory location.
Till now there is no problem. My issue is that I have two instances of two variables as string type
a = 'yasser'
b = 'yasser'
a is b
This code returns True
while
a = 'yasser!'
b = 'yasser!'
a is b
This returns False althought these are of string types. Any explanation..?
The 'is' keyword evaluates to true if the true arguments are from the same object. In the cases you had above, all of the ones that evaluate to true are from the same object, however, while those two strings are identical, they are not the same object. You can read more about it here.

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.

Python - comparing long/integer values with == and is [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Python “is” operator behaves unexpectedly with integers
Ran into something odd last night where doing
if max_urls is 0:
max_urls = 10
would always return false... even when max_urls was 0.... it was getting assigned from the database. When I did a
print type(max_urls)
would return
<type 'long'> 0
which seemed right but it would always return false.
If I changed it to
if max_urls == 0:
max_urls = 10
then finally it would return true when it was 0. Why the difference between == and is?
== is a value comparison, is is an object identity (memory location) comparison. You will often see that comparisons like max_urls is 0 will give the intended result because small values are usually cached in Python, but you always want to be using == instead of is when checking equality because this behavior cannot be relied upon.
Here is a brief example illustrating this:
>>> a = 0
>>> (a == 0, a is 0)
(True, True)
>>> a = 1000
>>> (a == 1000, a is 1000)
(True, False)
The is operator checks that two references point to the same object. You are testing if long(0) is the same object as int(0), and the answer is no. This will be crystal clear if you print their object ids:
>>> max_urls = long(0)
>>> id(max_urls)
335952
>>> id(0)
8402324
== on the other hand checks that two values are equivalent, even if they are not the exact same object. For instance:
>>> a = 777
>>> b = 777
>>> a is b
False
>>> a == b
True
>>> id(a)
8404568
>>> id(b)
8404640
Note: It is important that I used 777 and not a smaller number like 1 or 2. Quoting from the Python manual:
The current implementation keeps an array of integer objects for all integers between -5 and 256, when you create an int in that range you actually just get back a reference to the existing object.

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.

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

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.

Categories