Skip to content

Instantly share code, notes, and snippets.

@waylan
Created December 12, 2014 14:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save waylan/863c2da2b272c5aea99c to your computer and use it in GitHub Desktop.
Save waylan/863c2da2b272c5aea99c to your computer and use it in GitHub Desktop.
Class in which only one instance of each subclass can exist in a set. Not sure if there is a better way to do this, but it works. Although I don't like that overriding `__eg__` breaks other things.
class Foo(object):
def __hash__(self):
return hash('.'.join([self.__class__.__module__, self.__class__.__name__]))
def __eq__(a, b):
return a.__hash__() == b.__hash__()
class Bar(Foo):
pass
class Baz(Foo):
pass
f1 = Foo()
f2 = Foo()
b1 = Bar()
b2 = Bar()
bz = Baz()
assert f1 == f2 # This is not actually True but needed for set to work
assert f1 is not f2 # Must use `is` to compare not `__eq__`.
assert f1 != b1 # As it should be
instances = [f1, f2, b1, b2, bz]
uniques = set(instances) # => [f1, b1, bz] albeit unordered
assert len(uniques) == 3 # Yay, it works!
#for i in [f1, b1, bz]:
# assert i in uniques # Passes, but pointless; see next loop below
#for i in [f2, b2]:
# assert i not in uniques # This fails as it uses `__eq__`
for i in uniques:
assert i is f1 or i is b1 or i is bz # That'a better
for i in uniques:
assert i is not f2 and i is not b2 # Much better, but a pain
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment