Python None Comparison: Should I Use "Is" or ==

Python None comparison: should I use is or ==?

Summary:

Use is when you want to check against an object's identity (e.g. checking to see if var is None). Use == when you want to check equality (e.g. Is var equal to 3?).

Explanation:

You can have custom classes where my_var == None will return True

e.g:

class Negator(object):
def __eq__(self,other):
return not other

thing = Negator()
print thing == None #True
print thing is None #False

is checks for object identity. There is only 1 object None, so when you do my_var is None, you're checking whether they actually are the same object (not just equivalent objects)

In other words, == is a check for equivalence (which is defined from object to object) whereas is checks for object identity:

lst = [1,2,3]
lst == lst[:] # This is True since the lists are "equivalent"
lst is lst[:] # This is False since they're actually different objects

What is the difference between is None and == None

The answer is explained here.

To quote:

A class is free to implement
comparison any way it chooses, and it
can choose to make comparison against
None mean something (which actually
makes sense; if someone told you to
implement the None object from
scratch, how else would you get it to
compare True against itself?).

Practically-speaking, there is not much difference since custom comparison operators are rare. But you should use is None as a general rule.

Should I just use `==` to compare to `(None, None)` tuple?

You should use ==, but indeed it's not "obvious" that using is would fail.

For example

def foo():
return (1, 2)

print(foo() is foo())

MAY actually return True (it does in CPython, not sure about other implementations).

Tuples are NOT to be considered entities, but values. Identity on values shouldn't be used as it may match or not (like happens for example for strings or numbers).

If in the code above you use [1, 2] instead of (1, 2) then it's guaranteed that is will return False because lists are entities, not values, and identity can be used in predictable ways.

Should I compare with None explicitly

It depends on the values your variable may take and the expectations your code has. If your variable may take on other falsey values, then yes, the difference between None and, say, [] may be significant and you need to explicitly check for is None.

But not always. What if your value is a falsey [], and you're writing an if foo: to decide whether you have a value that needs processing? Well, an empty list might not need processing either, since it's empty. So both None and [] can be treated the same. In this case you'd need to explicitly check for is None and and empty list, in which case if foo: already encapsulates both very succinctly.

In your case, if the variable can be either None or a Thread, there's no difference whether you add is not None or not, it will behave identically in both cases. So why make it more verbose than it needs to be?

There's no one rule that fits all situations.

identity versus equality for None in Python

The reason people use is is because there is no advantage to using ==. It is possible to write objects that compare equal to None, but it is uncommon.

class A(object):
def __eq__(self, other):
return True

print A() == None

Output:

True

The is operator is also faster, but I don't consider this fact important.

Is there a difference between == and is ?

is will return True if two variables point to the same object (in memory), == if the objects referred to by the variables are equal.

>>> a = [1, 2, 3]
>>> b = a
>>> b is a
True
>>> b == a
True

# Make a new copy of list `a` via the slice operator,
# and assign it to variable `b`
>>> b = a[:]
>>> b is a
False
>>> b == a
True

In your case, the second test only works because Python caches small integer objects, which is an implementation detail. For larger integers, this does not work:

>>> 1000 is 10**3
False
>>> 1000 == 10**3
True

The same holds true for string literals:

>>> "a" is "a"
True
>>> "aa" is "a" * 2
True
>>> x = "a"
>>> "aa" is x * 2
False
>>> "aa" is intern(x*2)
True

Please see this question as well.

Comparing None with built-in types using arithmetic operators?

The only meaningful comparison you can really use with None is if obj is None: (or if obj is not None:).

Comparison between different types has been removed from Python 3 for good reasons - they were a common source of errors and lead to confusion. For example

>>> "3" < 4
False

In Python 3, you get a TypeError when comparing values of different types like str vs. int or anything vs. None.

>>> None < 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: NoneType() < int()

(I mean "comparing" in the sense of trying to determine which of two values is larger/smaller. Comparison for equality is OK - it will always return False if two object are of different types.)

I haven't found a reference in the docs for this, but in Learning Python, 4th edition, Mark Lutz writes on page 204:

[...] Comparisons of differently typed objects (e.g., a string and a
list) work — the language defines a fixed ordering among different
types, which is deterministic, if not aesthetically pleasing. That is,
the ordering is based on the names of the types involved: all integers
are less than all strings, for example, because "int" is less than
"str".



Related Topics



Leave a reply



Submit