Is there any difference between "foo is None" and "foo == None"? - python

Is there any difference between:
if foo is None: pass
and
if foo == None: pass
The convention that I've seen in most Python code (and the code I myself write) is the former, but I recently came across code which uses the latter. None is an instance (and the only instance, IIRC) of NoneType, so it shouldn't matter, right? Are there any circumstances in which it might?

is always returns True if it compares the same object instance
Whereas == is ultimately determined by the __eq__() method
i.e.
>>> class Foo(object):
def __eq__(self, other):
return True
>>> f = Foo()
>>> f == None
True
>>> f is None
False

You may want to read this object identity and equivalence.
The statement 'is' is used for object identity, it checks if objects refer to the same instance (same address in memory).
And the '==' statement refers to equality (same value).

A word of caution:
if foo:
# do something
Is not exactly the same as:
if x is not None:
# do something
The former is a boolean value test and can evaluate to false in different contexts. There are a number of things that represent false in a boolean value tests for example empty containers, boolean values. None also evaluates to false in this situation but other things do too.

(ob1 is ob2) equal to (id(ob1) == id(ob2))

The reason foo is None is the preferred way is that you might be handling an object that defines its own __eq__, and that defines the object to be equal to None. So, always use foo is None if you need to see if it is infact None.

There is no difference because objects which are identical will of course be equal. However, PEP 8 clearly states you should use is:
Comparisons to singletons like None should always be done with is or is not, never the equality operators.

is tests for identity, not equality. For your statement foo is none, Python simply compares the memory address of objects. It means you are asking the question "Do I have two names for the same object?"
== on the other hand tests for equality as determined by the __eq__() method. It doesn't cares about identity.
In [102]: x, y, z = 2, 2, 2.0
In [103]: id(x), id(y), id(z)
Out[103]: (38641984, 38641984, 48420880)
In [104]: x is y
Out[104]: True
In [105]: x == y
Out[105]: True
In [106]: x is z
Out[106]: False
In [107]: x == z
Out[107]: True
None is a singleton operator. So None is None is always true.
In [101]: None is None
Out[101]: True

For None there shouldn't be a difference between equality (==) and identity (is). The NoneType probably returns identity for equality. Since None is the only instance you can make of NoneType (I think this is true), the two operations are the same. In the case of other types this is not always the case. For example:
list1 = [1, 2, 3]
list2 = [1, 2, 3]
if list1==list2: print "Equal"
if list1 is list2: print "Same"
This would print "Equal" since lists have a comparison operation that is not the default returning of identity.

#Jason:
I recommend using something more along the lines of
if foo:
#foo isn't None
else:
#foo is None
I don't like using "if foo:" unless foo truly represents a boolean value (i.e. 0 or 1). If foo is a string or an object or something else, "if foo:" may work, but it looks like a lazy shortcut to me. If you're checking to see if x is None, say "if x is None:".

Some more details:
The is clause actually checks if the two objects are at the same
memory location or not. i.e whether they both point to the same
memory location and have the same id.
As a consequence of 1, is ensures whether, or not, the two lexically represented objects have identical attributes (attributes-of-attributes...) or not
Instantiation of primitive types like bool, int, string(with some exception), NoneType having a same value will always be in the same memory location.
E.g.
>>> int(1) is int(1)
True
>>> str("abcd") is str("abcd")
True
>>> bool(1) is bool(2)
True
>>> bool(0) is bool(0)
True
>>> bool(0)
False
>>> bool(1)
True
And since NoneType can only have one instance of itself in the python's "look-up" table therefore the former and the latter are more of a programming style of the developer who wrote the code(maybe for consistency) rather then having any subtle logical reason to choose one over the other.

John Machin's conclusion that None is a singleton is a conclusion bolstered by this code.
>>> x = None
>>> y = None
>>> x == y
True
>>> x is y
True
>>>
Since None is a singleton, x == None and x is None would have the same result. However, in my aesthetical opinion, x == None is best.

a is b # returns true if they a and b are true alias
a == b # returns true if they are true alias or they have values that are deemed equivalence
a = [1,3,4]
b = a[:] #creating copy of list
a is b # if gives false
False
a == b # gives true
True

Related

Do the commands "x is None" and "x == None" return always the same result if x is immutable? [duplicate]

This question already has answers here:
Python None comparison: should I use "is" or ==?
(6 answers)
Closed 2 years ago.
If the Python name x in Python refers to an immutable value, would these two statements return the same result and do an equivalent / identical check?
x is None vs x == None
I couldn't find an exact duplicate of this question, but perhaps it's still answered implicitly elsewhere, but here are some related questions:
Python: if not val, vs if val is None
Why does `None is None is None` return True?
It has nothing to do with the immutability of x. None is a singleton for which is and == return identical results, unless the type of x defines a weird __eq__ method. The name x is either bound or not bound to the same object as None. If not, the identity check will always be False, regardless of what other type it is. The result of the equality check is up to the type of x, but will be the same as the identity check for most sane classes.
Now the caveat is that while you can't override is, since that's an identity check done by the interpreter, you can override ==. Aside from speed and consistency, here's a toy example showing why x is None is preferable to x == None:
class Test:
def __eq__(self, other):
if other is None:
return True
return self is other
>>> Test() == None
True
>>> None == Test()
True
>>> Test() is None
False
>>> None is Test()
False
The reason that both Test () == None and None == Test() return the same result has to do with how comparisons are evaluated, and the fact that None does not define an explicit __eq__ method. Normally, the interpreter calls type(left).__eq__(left, right) on the operands. If the left operand's type does not define __eq__ or the method returns NotImplemented, it attempts type(right).__eq__(right, left). Only if both fail does it fail over to a built-in identity check. Since None doesn't define an equality check, it will always use the check defined by the other object before failing over to the identity check.

Comparing None to several variables in Python3

Is there anyone that can tell my why I get this type of return value?
>>> a = 7
>>> b = None
>>> bool(a and b)
False
>>> bool((a is None) and (b is None))
False
>>> bool((a and b) is None) # (a and b) eq False
True
>>> bool(False is None)
False
I just can't understand why this is happening.
To explain
>>> 7 and None
None
>>> bool(None)
False
So to answer:
a and b gives None and not False as you put in comment.
bool(a and b) gives False
So then when you replace a and b by its real value:
you get bool(None is None) which is True.
I believe you had bool(bool(a and b) is None) in mind, which would give False
Python's and actually returns the last value tested. For x and y, if x is false, it will return x; if x is true, it will return y. For example:
>>> 0 and ''
0
>>> 0 and 'x'
0
>>> 1 and ''
''
>>> 1 and 'x'
'x'
So when you do a and b, you get None.
Source: Documentation: Boolean Operations — and, or, not
All Python builtins and most instances have implicit truth values thanks to their __bool__ magic methods. In your case, you are working with the builtin types of int and None. In pure python, the __bool__ method for an int would like something like the following:
class int(object):
...
def __bool__(self):
return self != 0 # True as long as not equal to 0
...
And for a None it would be the following:
class NoneType(object):
...
def __bool__(self):
return False # Always False
...
Whenever an operation is done that requires the variable to be treated as a boolean (and, or, not, bool casting), these __bool__ magic methods are used to get their corresponding instance's truth value.
So with this in mind, let's look at your expressions one-by-one.
>>> bool(a and b)
False
a is the integer 7, so by its __bool__ magic method, it has a positive truth value (True). b is None, and it has a negative truth value (False). When you and variables in Python, if the first and operand has a positive truth value, and will always return the second operand (the opposite behavior can be seen with or). More information on this can be found here. So when you do a and b, None is returned because a has a positive truth value. The resulting None is then casted to a bool which as shown in None's __bool__ method above, will be False.
>>> bool((a is None) and (b is None))
False
This evaluates to False as a is not None. Here, since you are using is in the statements, you are not comparing truth value, but you are checking if they are the same object. Since 7 and None are not the same instance, it results to False, causing the rest of the statement to evaluate to False.
>>> bool((a and b) is None) # (a and b) eq False (should be None)
True
Following up from the first one, a and b will return None. since None is the same instance as None, None is None evaluates to True. The casting to bool is redundant.
>>> bool(False is None)
False
Lastly, here we are once again checking if False and None are the same instance. As they are not, this evaluates to False and the casting to bool is once again redundant.
Consider these two facts:
None is false
and returns true if both variables are true.
In every case that misleads you, you did not consider these facts.

Is `if x:` completely equivalent to `if bool(x) is True:`?

For a small testing framework we are writing I'm trying to provide some utility functions.
One of them is supposed to be equivalent to if x: but if that is completely equivallent to if bool(x) is True: then I could only provide one function to check if x is True: and if x:.
Is the negation of that also equivalent? if bool(x) is False: equal to if not x:?
if x: is completely equivalent to testing for the boolean truth value, yes.
From the if statement documentation:
It selects exactly one of the suites by evaluating the expressions one by one until one is found to be true (see section Boolean operations for the definition of true and false)
where the Boolean operations section details how truth is defined. The bool() function follows those exact same rules:
Return a Boolean value, i.e. one of True or False. x is converted using the standard truth testing procedure.
The Standard Types documentation has a Truth Value Testing section:
Any object can be tested for truth value, for use in an if or while condition or as operand of the Boolean operations below.
not simply inverts that same truth value; so if x is considered true by the above rules not x returns False, and True otherwise.
Be careful: in Python 2, the built-in names False and True can be masked by setting a global:
>>> True = False
>>> True
False
and thus is identity tests may be fooled by that re-assignment as well. Python 3 makes False and True keywords.
Your utility function should not need to use bool(x) is True or bool(x) is False. All you need is bool(x) and not bool(x), as these already produce True and False objects. bool() and not can't return anything else, using is True or is False on these is extremely redundant.
Last but not least, try not to re-invent the testing wheel. The Python standard library comes with a unittest library; it has both assertTrue and assertFalse functions, and the implementation of these functions just use if and if not.
Yes. These are equivalent. The rules used by if are the same as those used by bool. not simply inverts these values without changing the logic for determining truthiness or falseness.
additionally to the answer of #Martijn, if what you are building are some class, you can define what behavior you want it to have in a truth testing case like ìf x by defining __bool__ function.
>>> class A:
pass
>>> a=A()
>>> if a:
print("this instance class is truthish")
this instance class is truthish
>>> a is True
False
>>> bool(a) is True
True
>>>
the default behavior for a user defined class is to always be true in a truth test, to change that just define __bool__ (__nonzero__ in python 2) so it adjust accordingly to the semantic of the class, like for example:
>>> class Switch:
def __init__(self, state="off"):
self.state = state
def __bool__(self):
if self.state == "on":
return True
return False
>>> x=Switch()
>>> if x:
print("this instance class is truthish")
>>> x is True
False
>>> bool(x) is True
False
>>> x.state="on"
>>> if x:
print("this instance class is truthish")
this instance class is truthish
>>> x is True
False
>>> bool(x) is True
True
>>>

How is the 'is' keyword implemented in Python?

... the is keyword that can be used for equality in strings.
>>> s = 'str'
>>> s is 'str'
True
>>> s is 'st'
False
I tried both __is__() and __eq__() but they didn't work.
>>> class MyString:
... def __init__(self):
... self.s = 'string'
... def __is__(self, s):
... return self.s == s
...
>>>
>>>
>>> m = MyString()
>>> m is 'ss'
False
>>> m is 'string' # <--- Expected to work
False
>>>
>>> class MyString:
... def __init__(self):
... self.s = 'string'
... def __eq__(self, s):
... return self.s == s
...
>>>
>>> m = MyString()
>>> m is 'ss'
False
>>> m is 'string' # <--- Expected to work, but again failed
False
>>>
Testing strings with is only works when the strings are interned. Unless you really know what you're doing and explicitly interned the strings you should never use is on strings.
is tests for identity, not equality. That means Python simply compares the memory address a object resides in. is basically answers the question "Do I have two names for the same object?" - overloading that would make no sense.
For example, ("a" * 100) is ("a" * 100) is False. Usually Python writes each string into a different memory location, interning mostly happens for string literals.
The is operator is equivalent to comparing id(x) values. For example:
>>> s1 = 'str'
>>> s2 = 'str'
>>> s1 is s2
True
>>> id(s1)
4564468760
>>> id(s2)
4564468760
>>> id(s1) == id(s2) # equivalent to `s1 is s2`
True
id is currently implemented to use pointers as the comparison. So you can't overload is itself, and AFAIK you can't overload id either.
So, you can't. Unusual in python, but there it is.
The Python is keyword tests object identity. You should NOT use it to test for string equality. It may seem to work frequently because Python implementations, like those of many very high level languages, performs "interning" of strings. That is to say that string literals and values are internally kept in a hashed list and those which are identical are rendered as references to the same object. (This is possible because Python strings are immutable).
However, as with any implementation detail, you should not rely on this. If you want to test for equality use the == operator. If you truly want to test for object identity then use is --- and I'd be hard-pressed to come up with a case where you should care about string object identity. Unfortunately you can't count on whether two strings are somehow "intentionally" identical object references because of the aforementioned interning.
The is keyword compares objects (or, rather, compares if two references are to the same object).
Which is, I think, why there's no mechanism to provide your own implementation.
It happens to work sometimes on strings because Python stores strings 'cleverly', such that when you create two identical strings they are stored in one object.
>>> a = "string"
>>> b = "string"
>>> a is b
True
>>> c = "str"+"ing"
>>> a is c
True
You can hopefully see the reference vs data comparison in a simple 'copy' example:
>>> a = {"a":1}
>>> b = a
>>> c = a.copy()
>>> a is b
True
>>> a is c
False
If you are not afraid of messing up with bytecode, you can intercept and patch COMPARE_OP with 8 ("is") argument to call your hook function on objects being compared. Look at dis module documentation for start-in.
And don't forget to intercept __builtin__.id() too if someone will do id(a) == id(b) instead of a is b.
'is' compares object identity whereas == compares values.
Example:
a=[1,2]
b=[1,2]
#a==b returns True
#a is b returns False
p=q=[1,2]
#p==q returns True
#p is q returns True
is fails to compare a string variable to string value and two string variables when the string starts with '-'. My Python version is 2.6.6
>>> s = '-hi'
>>> s is '-hi'
False
>>> s = '-hi'
>>> k = '-hi'
>>> s is k
False
>>> '-hi' is '-hi'
True
You can't overload the is operator. What you want to overload is the == operator. This can be done by defining a __eq__ method in the class.
You are using identity comparison. == is probably what you want. The exception to this is when you want to be checking if one item and another are the EXACT same object and in the same memory position. In your examples, the item's aren't the same, since one is of a different type (my_string) than the other (string). Also, there's no such thing as someclass.__is__ in python (unless, of course, you put it there yourself). If there was, comparing objects with is wouldn't be reliable to simply compare the memory locations.
When I first encountered the is keyword, it confused me as well. I would have thought that is and == were no different. They produced the same output from the interpreter on many objects. This type of assumption is actually EXACTLY what is... is for. It's the python equivalent "Hey, don't mistake these two objects. they're different.", which is essentially what [whoever it was that straightened me out] said. Worded much differently, but one point == the other point.
the
for some helpful examples and some text to help with the sometimes confusing differences
visit a document from python.org's mail host written by "Danny Yoo"
or, if that's offline, use the unlisted pastebin I made of it's body.
in case they, in some 20 or so blue moons (blue moons are a real event), are both down, I'll quote the code examples
###
>>> my_name = "danny"
>>> your_name = "ian"
>>> my_name == your_name
0 #or False
###
###
>>> my_name[1:3] == your_name[1:3]
1 #or True
###
###
>>> my_name[1:3] is your_name[1:3]
0
###
Assertion Errors can easily arise with is keyword while comparing objects. For example, objects a and b might hold same value and share same memory address. Therefore, doing an
>>> a == b
is going to evaluate to
True
But if
>>> a is b
evaluates to
False
you should probably check
>>> type(a)
and
>>> type(b)
These might be different and a reason for failure.
Because string interning, this could look strange:
a = 'hello'
'hello' is a #True
b= 'hel-lo'
'hel-lo' is b #False

Python != operation vs "is not"

In a comment on this question, I saw a statement that recommended using
result is not None
vs
result != None
What is the difference? And why might one be recommended over the other?
== is an equality test. It checks whether the right hand side and the left hand side are equal objects (according to their __eq__ or __cmp__ methods.)
is is an identity test. It checks whether the right hand side and the left hand side are the very same object. No methodcalls are done, objects can't influence the is operation.
You use is (and is not) for singletons, like None, where you don't care about objects that might want to pretend to be None or where you want to protect against objects breaking when being compared against None.
First, let me go over a few terms. If you just want your question answered, scroll down to "Answering your question".
Definitions
Object identity: When you create an object, you can assign it to a variable. You can then also assign it to another variable. And another.
>>> button = Button()
>>> cancel = button
>>> close = button
>>> dismiss = button
>>> print(cancel is close)
True
In this case, cancel, close, and dismiss all refer to the same object in memory. You only created one Button object, and all three variables refer to this one object. We say that cancel, close, and dismiss all refer to identical objects; that is, they refer to one single object.
Object equality: When you compare two objects, you usually don't care that it refers to the exact same object in memory. With object equality, you can define your own rules for how two objects compare. When you write if a == b:, you are essentially saying if a.__eq__(b):. This lets you define a __eq__ method on a so that you can use your own comparison logic.
Rationale for equality comparisons
Rationale: Two objects have the exact same data, but are not identical. (They are not the same object in memory.)
Example: Strings
>>> greeting = "It's a beautiful day in the neighbourhood."
>>> a = unicode(greeting)
>>> b = unicode(greeting)
>>> a is b
False
>>> a == b
True
Note: I use unicode strings here because Python is smart enough to reuse regular strings without creating new ones in memory.
Here, I have two unicode strings, a and b. They have the exact same content, but they are not the same object in memory. However, when we compare them, we want them to compare equal. What's happening here is that the unicode object has implemented the __eq__ method.
class unicode(object):
# ...
def __eq__(self, other):
if len(self) != len(other):
return False
for i, j in zip(self, other):
if i != j:
return False
return True
Note: __eq__ on unicode is definitely implemented more efficiently than this.
Rationale: Two objects have different data, but are considered the same object if some key data is the same.
Example: Most types of model data
>>> import datetime
>>> a = Monitor()
>>> a.make = "Dell"
>>> a.model = "E770s"
>>> a.owner = "Bob Jones"
>>> a.warranty_expiration = datetime.date(2030, 12, 31)
>>> b = Monitor()
>>> b.make = "Dell"
>>> b.model = "E770s"
>>> b.owner = "Sam Johnson"
>>> b.warranty_expiration = datetime.date(2005, 8, 22)
>>> a is b
False
>>> a == b
True
Here, I have two Dell monitors, a and b. They have the same make and model. However, they neither have the same data nor are the same object in memory. However, when we compare them, we want them to compare equal. What's happening here is that the Monitor object implemented the __eq__ method.
class Monitor(object):
# ...
def __eq__(self, other):
return self.make == other.make and self.model == other.model
Answering your question
When comparing to None, always use is not. None is a singleton in Python - there is only ever one instance of it in memory.
By comparing identity, this can be performed very quickly. Python checks whether the object you're referring to has the same memory address as the global None object - a very, very fast comparison of two numbers.
By comparing equality, Python has to look up whether your object has an __eq__ method. If it does not, it examines each superclass looking for an __eq__ method. If it finds one, Python calls it. This is especially bad if the __eq__ method is slow and doesn't immediately return when it notices that the other object is None.
Did you not implement __eq__? Then Python will probably find the __eq__ method on object and use that instead - which just checks for object identity anyway.
When comparing most other things in Python, you will be using !=.
Consider the following:
class Bad(object):
def __eq__(self, other):
return True
c = Bad()
c is None # False, equivalent to id(c) == id(None)
c == None # True, equivalent to c.__eq__(None)
None is a singleton, and therefore identity comparison will always work, whereas an object can fake the equality comparison via .__eq__().
>>> () is ()
True
>>> 1 is 1
True
>>> (1,) == (1,)
True
>>> (1,) is (1,)
False
>>> a = (1,)
>>> b = a
>>> a is b
True
Some objects are singletons, and thus is with them is equivalent to ==. Most are not.

Categories

Resources