Shobhit Shobhit - 5 months ago 35
Python Question

Interaction of a hashable class with Enum in Python

I have a defined a class which I am trying to make hashable. Additionally, there's an enum which uses objects of this class as values of its enum members.

from enum import Enum

class Dummy(object):
def __init__(self, name, property_): = name # can only be a string = property_ # can only be a string

def __hash__(self):
# print "Hash called for ", self
# print("----")
return hash(

def __eq__(self, other):
# print "Eq called for: "
# print self
# print other
return ( ==

def __ne__ (self, other):
return not (self == other)

def __str__(self):
return ( + "$" +

class Property(Enum):
cool = Dummy("foo", "cool")
hot = Dummy("bar", "hot")

Although this works fine, I noticed -- by un-commenting the
statements -- that the
magic methods are invoked for the two enum member values. Why is this so? Aren't these used only during hashing and equality checks?

Additionally, if I change the enum class to the following, all hell breaks loose.

class Property(Enum):
cool = Dummy("foo", "cool")
hot = [Dummy("bar-1", "hot-1"), Dummy("bar-2", "hot-2")]

magic method seems to be called for the
object corresponding to
and the list corresponding to
, as evident from the output:

Hash called for foo$cool
Eq called for:
[<__main__.Dummy object at 0x7fd36633f2d0>, <__main__.Dummy object at 0x7fd36633f310>]
Traceback (most recent call last):
File "", line 28, in <module>
class Property(Enum):
File "/blah/.local/lib/python2.7/site-packages/enum/", line 237, in __new__
if canonical_member.value == enum_member._value_:
File "", line 19, in __eq__
return ( is
AttributeError: 'list' object has no attribute 'property'

Why is this happening? Why are the magic methods called in the first place, and why is
called on a class object and a list?

Please note that this is only a representative example, and the real use-case makes this design -- enum with values as lists of hashable class objects -- appear less weird.


The Enum class is comparing its member object values to see if any are aliases of another. For example, in the following Enum, both a and b represent the same value, so only a should show up in the member list (aliases don't):

class A(Enum):

You can verify this by looking at the source code for the line that did the equality check: source

For the hashing, this is done to provide a by-value lookup of the enum members. Again, this can be found in the source code