Skip to content

Instantly share code, notes, and snippets.

@bradmontgomery
Last active August 29, 2015 13:57
Show Gist options
  • Save bradmontgomery/9608426 to your computer and use it in GitHub Desktop.
Save bradmontgomery/9608426 to your computer and use it in GitHub Desktop.
#!/bin/bash
source ~/.profile; workon p3; unset PYTHONPATH; ipython3
class Person:
def __init__(self, name, id):
self.id = id
self.name = name
def __eq__(self, other):
return self.id == other.id
def __ne__(self, other):
return not self.__eq__(other)
def clone_person(p):
return Person(p.name, p.id)

Built-in equality operators

To test for Equality, use the == operator.

>>> 1 == 1
True

>>> 1 == 0
False

Not equal, use the !=

>>> 1 != 1
False

>>> 1 != 0
True

Python 2 supports <> for not-equal. Don't use it.

>>> 1 <> 0
True

>>> 1 <> 1
False

Now, what about the is and is not operators. These are for object identity. First, let's look at id:

>>> a = 1
>>> id(a)  # Returns the identity of an object
4297277920

>>> id(1)
4297277920

>>> a is 1
True

The identity is a constant integer, and is guaranteed to be unique for the object's lifetime. In CPython, it's the memory address for the object. The is (and is not) operations essentially compare the value returned by the built-in id function.

Notice that a is 1 returns True, but watch this:

>>> a = 257
>>> b = 257
>>> a is b
False

Python 2 (not sure about 3?) does some optimization for integers so which at first makes the is operator appear to work as the == operator.

Let's try with strings:

>>> a = "hello world"
>>> b = "hello world"
>>> a is b
False

>>> a == b
True

In general, if you want to compare two values, use ==. However, is is the most appropriate comparison operator when comparing a value to None, True, or False.

>>> (1 > 0) is True
True

>>> (1 > 0) is False
False

>>> a = None
>>> a is None
True

>>> a = 1
>>> a is None
False

So remember:

  • == tests equality
  • is tests identity

Comparing Custom Objects

Assume we have the following Person class:

class Person:
    def __init__(self, name, id):
        self.id = id
        self.name = name

What happens if we create two instances with the same values?

>>> a = Person("jane", 1)
>>> b = Person("jane", 1)

>>> a == b
False

>>> a is b
False

>>> id(a)
4329269904

>>> id(b)
4329229008

They're different objects, stored in different memory locations, so Python thinks they're different. However, from a logical of view, if a Person has the same name and id, they could be considered equal.

That's why python gives us a way to customize comparison between objects: Magic Methods.

  • __eq__(self, other) Defines behavior for the == operator.
  • __ne__(self, other) Defines behavior for the != operator.

Let's add these to our Person class.

class Person:
    def __init__(self, name, id):
        self.id = id
        self.name = name

    def __eq__(self, other):
        return self.id == other.id

    def __ne__(self, other):
        return not self.__eq__(other)

And now we can compare

>>> a = Person("jane", 1)
>>> b = Person("jane", 1)

>>> a == b
True

>>> a != b
False

So, even it Jane changes her name, she's still the same person.

>>> a.name = "judy"
>>> a == b
True
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment