This Blog continues on http://aliafshar.github.io/blog

Tuesday, July 17, 2012

Making two instances behave as the same instance in Python

The use-case is this:

# Two instances of the same class
x = A()
y = A()

x in {y: 1} # True

So we want to be able to check an instance's presence inside a dict, set, or anything that hashes an instance for a key.

You need two things:

__hash__ method which returns an integer
__eq__ method which tests equality against another instance and returns a boolean

__hash__ method returns an integer which is used as the hash. I didn't want to invent a hash method, so instead I used the hash of a tuple, which seems a reasonable hashable type to use, but you could use an integer or string or anything. I wanted the tuple contents to be attributes of the instance, with the added side effect that the instance would pass the test:

x is (1, 2) # True

Here it is:

def __hash__(self):
  return hash((self.name, self.age, self.location))

That is not enough though, if you implement __hash__ you must also implement __eq__, which is simple enough:

def __eq__(self, other):
  return hash(self) == hash(other)

Ok that is just a bit cheap, and you could compare the tuple's values directly if you want to. Here is the complete (toy) implementation:

class Person(object):
  def __init__(self, name, age, location):
    self.name = name
    self.age = age
    self.location = location

  def __hash__(self):
    return hash((self.name, self.age, self.location))

  def __eq__(self, other):
    return hash(self) == hash(other)