330

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?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
viksit
  • 7,542
  • 9
  • 42
  • 54
  • 5
    dupe: http://stackoverflow.com/questions/1504717/python-vs-is-comparing-strings-is-fails-sometimes-why – SilentGhost Feb 05 '10 at 21:06
  • 3
    Hmm. While the answer to both questions is the same concept, I think the upvotes and detailed answers here do contribute independently to the concept of identity and equality testing. – viksit Feb 05 '10 at 23:59
  • 3
    Possible duplicate of [Why does comparing strings using either '==' or 'is' sometimes produce a different result?](https://stackoverflow.com/questions/1504717/why-does-comparing-strings-using-either-or-is-sometimes-produce-a-differe) – Michael Wang May 24 '19 at 17:04

5 Answers5

370

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

Roberto Bonvallet
  • 31,943
  • 5
  • 40
  • 57
Thomas Wouters
  • 130,178
  • 23
  • 148
  • 122
  • 5
    Thanks for the answer - could you elaborate on situations when an object can break, being compared to None? – viksit Feb 05 '10 at 19:49
  • 6
    @viksit. `None` has few methods and almost no attributes. If your `__eq__` test expected a method or attribute, it might break. `def __eq__( self, other ): return self.size == other.size`. For example, will break if `other` happens to be `None`. – S.Lott Feb 05 '10 at 20:11
  • 58
    My favorite way to comprehend this is: Python's `is` is like Java's `==`. Python's `==` is like Java's `.equals()`. Of course this only helps if you know Java. – Tyler Feb 05 '10 at 20:54
  • 4
    @MatrixFrog: In PHP or JavaScript we would say that `is` is like `===` (very equal), and conversely `is not` is like `!==` (not exactly equal). – Orwellophile Apr 02 '17 at 01:43
  • 4
    Is `is not` a single operator or is it just negating the result of `is` internally like `not foo is bar`? – Asad Moosvi Aug 19 '17 at 20:25
  • Great answer! To add on, an example of an object that would be break when being compared to None via an equality test would be the `dateutil.relativedelta.relativedelta` object. When compared to `!= None`, it would return False, and when compared to `== None`, it would also return False. Weird, I know. – FriskySaga Jul 30 '21 at 02:35
  • @Asad Moosvi I was wondering the same thing, but we can check that `is not` is indeed a single operator: `False is not None # True` but `False is (not None) # False` – optical Feb 15 '23 at 21:10
178

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 !=.

Wesley
  • 10,652
  • 4
  • 37
  • 52
50

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)
Alok Singhal
  • 93,253
  • 21
  • 125
  • 158
24

None is a singleton, and therefore identity comparison will always work, whereas an object can fake the equality comparison via .__eq__().

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • Ah interesting! In which situations might one want to fake the equality comparison btw? I'm guessing this has security implications in some way. – viksit Feb 05 '10 at 19:47
  • 1
    It's not about faking equality, it's about *implementing* equality. There are lots of reasons to want to define how an object compares to another. – Thomas Wouters Feb 05 '10 at 19:48
  • 1
    I would say it's more *confusion* implications than security implications. – Greg Hewgill Feb 05 '10 at 19:48
  • 2
    I have not come up against a reason to fake equality against `None`, but incorrect behavior regarding `None` could occur as a side effect of implementing equality against other types. It's not so much security implications as it is just correctness implications. – Ignacio Vazquez-Abrams Feb 05 '10 at 19:50
11
>>> () 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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ephemient
  • 198,619
  • 38
  • 280
  • 391
  • 4
    Most of these only work by coincidence/implementation detail. `()` and `1` are not inherently singletons. – Mike Graham Feb 05 '10 at 20:22
  • 1
    In the CPython implementation, the small integers (`-NSMALLNEGINTS <= n <= NSMALLPOSINTS`) and empty tuples *are* singletons. Indeed it's not documented nor guaranteed, but it's unlikely to change. – ephemient Feb 05 '10 at 20:27
  • 3
    It is how it is implemented, but it isn't meaningful or useful or educational. – Mike Graham Feb 06 '10 at 21:47
  • 1
    And in particular, CPython is not the only Python implementation. Relying on behaviour that can vary across Python implementations would seem to generally be a Bad Idea™ to me. – me_and Jan 07 '14 at 13:10