Is there any difference between "foo is None" and "foo == None"?
Asked Answered
A

12

231

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?

Aida answered 25/8, 2008 at 18:27 Comment(0)
R
274

is always returns True if it compares the same object instance, whereas == is ultimately determined by the __eq__() method.

i.e.

>>> class Foo:
        def __eq__(self, other):
            return True

>>> f = Foo()
>>> f == None
True
>>> f is None
False
Richmal answered 25/8, 2008 at 18:38 Comment(4)
You may want to add that None is a singleton so "None is None" is always True.Annam
And you may want to add that the is operator cannot be customized (overloaded by a user-defined class).Canuck
@study The method __eq__(self) is a special builtin method that determines how == is handled when used on a Python object. Here we have overridden it so that when == is used on objects of type Foo it always returns true. There isn't an equivalent method for the is operator and so the behaviour of is cannot be changed in the same way.Richmal
Is it because the definition of the foo class does not have a constructor, i.e., the init function?Rigamarole
M
51

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).

Mandorla answered 25/8, 2008 at 18:48 Comment(1)
I just tried a=1;b=1;print(a is b) # True. Any idea why a is b turn out to be true even if they seems to be 2 different object (different address in memory)?Kare
A
28

A word of caution:

if foo:
    # do something

Is not exactly the same as:

if foo 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.

Adara answered 26/8, 2008 at 13:44 Comment(0)
S
13

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

Sasnett answered 25/2, 2009 at 10:34 Comment(3)
... but (ob is ob2) is a LOT faster. Timeit says "(a is b)" is 0.0365 usec per loop and "(id(a)==id(b))" is 0.153 usec per loop. 4.2x faster!Footplate
the is version needs no function call, and no python-interpreter attribute lookup at all; the interpreter can immediately answer if ob1 is, in fact, ob2.Ryon
No, it does not. {} is {} is false and id({}) == id({}) can be (and is in CPython) true. See stackoverflow.com/questions/3877230Skysweeper
L
12

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.

Lem answered 28/5, 2010 at 21:15 Comment(0)
M
10

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.

Modernistic answered 19/5, 2013 at 15:35 Comment(0)
B
9

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
Borstal answered 19/12, 2014 at 4:5 Comment(0)
B
5

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.

Berkman answered 25/8, 2008 at 19:4 Comment(0)
B
4

@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:".

Bawl answered 25/8, 2008 at 21:35 Comment(3)
Checking for empty strings/lists with "if var" is the preferred way. Boolean conversion is well defined, and it is less code that even performs better. No reason to do "if len(mylist) == 0" for example.Lem
Wrong. Suppose foo = "". Then if foo will return false and the comment #foo is None is wrong.Speculative
Note to downvoters - my answer is quoting an answer that has since been deleted and disagreeing with it. If you don't like the code in my answer, you need to upvote. :-)Bawl
C
3

Some more details:

  1. 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.

  2. As a consequence of 1, is ensures whether, or not, the two lexically represented objects have identical attributes (attributes-of-attributes...) or not

  3. 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.

Cheese answered 19/5, 2013 at 15:8 Comment(3)
Everyone reading this: DO NOT use some_string is "bar" to compare strings EVER. There is NOT A SINGLE ACCEPTABLE REASON to do so and it WILL BREAK when you don't expect it. The fact that it works often is simply because CPython knows it would be stupid to create two immutable objects that have the same content. But it can happen nonetheless.Floozy
@Floozy does the answer have the tendency to be misconstrued? Though, upon reading it again I couldn't find it to be(with the mentioning of "some exceptions"). Your statement only holds for strings and not int, right?Cheese
Not really, but since you have that example in your answer I thought it'd be a good idea to warn users that it's a bad idea to actually use that. Maybe add something like "# cpython specific / not guaranteed" behind that line...Floozy
I
1

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.

Interbreed answered 27/3, 2011 at 19:31 Comment(1)
I disagree with the opinion at the end of this answer. When comparing with none explicitly, it's usually intended that the object in question is exactly the None object. By comparison, one seldom sees None used in any other context except to be similar to False with other values being truthy. In those cases it is more idiomatic to do something like if x: passRaye
V
0
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
Vonvona answered 3/4, 2019 at 7:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.