Coder Perfect

!= operation in Python vs. “is not” in Python

Problem

I saw a statement in a comment on this subject that suggested using

result is not None

vs

result != None

I’m curious as to what the differences are and why one could be preferred over the other.

Asked by viksit

Solution #1

== is a test for equality. It determines whether the right and left sides are equal objects (based on their __eq__ or __cmp__ methods).

It’s a test to see if you’re who you say you are. It determines whether the thing on the right and left sides are the same. There are no method calls, and objects have no influence on 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.

Answered by Thomas Wouters

Solution #2

Let me first define a few terms. Scroll down to “Answering your questions” if you just want your question addressed.

You can assign an object’s identity to a variable when you create it. After that, you can assign it to another variable. And then there was another.

>>> button = Button()
>>> cancel = button
>>> close = button
>>> dismiss = button
>>> print(cancel is close)
True

Cancel, close, and dismiss all refer to the same memory item in this scenario. There was just one Button object generated, and all three variables point to it. We say cancel, close, and dismiss all relate to the same thing; that is, they all refer to the same thing.

Item equality: When comparing two objects, it is frequently unimportant whether they relate to the same object in memory. You can specify your own rules for comparing two items with object equality. If you write if a == b:, you’re just saying if a. eq (b). This allows you to implement your own comparison logic by defining a __eq__ function on a.

Reasoning: Although two things contain the same data, they are not identical. (In memory, they are not the same entity.) Strings are an example.

>>> greeting = "It's a beautiful day in the neighbourhood."
>>> a = unicode(greeting)
>>> b = unicode(greeting)
>>> a is b
False
>>> a == b
True

Note that I’m using unicode strings because Python can reuse normal strings without having to create new ones in memory.

I have two unicode strings, a and b, in front of me. They both have the same content, but they are not the same memory object. When we compare them, though, we want them to be on a level playing field. The __eq__ method has been implemented by the unicode object in this case.

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 that on Unicode, __eq__ is clearly more efficient than this.

Rationale: Two objects may have different data, but if certain important data is the same, they are considered the same object. For instance, 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

I have two Dell monitors, a and b, in this room. They’re both made by the same company and have the same model number. They do not, however, share the same data or exist in memory as the same entity. When we compare them, though, we want them to be on a level playing field. The __eq__ method was implemented by the Monitor object in this case.

class Monitor(object):
    # ...

    def __eq__(self, other):
        return self.make == other.make and self.model == other.model

Always use is not when comparing to None. In Python, none is a singleton, meaning there is only one instance of it in memory at any given time.

This can be done extremely rapidly by comparing identities. Python compares the memory addresses of the object you’re referring to and the global None object – a lightning-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 forget to use __eq__? Then Python will most likely go for the object’s __eq__ method and use that instead, which just tests for object identity.

In Python, you’ll use!= to compare almost anything else.

Answered by Wesley

Solution #3

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)

Answered by Alok Singhal

Solution #4

Because none is a singleton, identity comparisons will always work, whereas an object can use. eq to fool the equality comparison.

Answered by Ignacio Vazquez-Abrams

Solution #5

>>> () is ()
True
>>> 1 is 1
True
>>> (1,) == (1,)
True
>>> (1,) is (1,)
False
>>> a = (1,)
>>> b = a
>>> a is b
True

Because some objects are singletons, is identical to == with them. The most of them aren’t.

Answered by ephemient

Post is based on https://stackoverflow.com/questions/2209755/python-operation-vs-is-not