Created
November 17, 2019 23:21
-
-
Save sjkillen/4a511bd41da3a2a7abfe37221beecf6d to your computer and use it in GitHub Desktop.
Lazy object hashing/equality checking for acyclic objects
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def refineddir(obj): | |
return tuple(prop for prop in dir(obj) if not prop.startswith("_") and not hasattr(getattr(obj, prop), "__call__")) | |
class DeepComparator: | |
def __init__(self, wrap): | |
self.wrap = wrap | |
def __eq__(self, other): | |
if isinstance(self, DeepComparator): | |
self = self.wrap | |
if isinstance(other, DeepComparator): | |
other = other.wrap | |
props = refineddir(self) | |
if props != refineddir(other): | |
return False | |
for prop in props: | |
mine = getattr(self, prop) | |
if type(mine).__eq__ == object.__eq__: | |
mine = DeepComparator(mine) | |
theirs = getattr(other, prop) | |
if type(theirs).__eq__ == object.__eq__: | |
theirs = DeepComparator(theirs) | |
if mine != theirs: | |
return False | |
return True | |
def __hash__(self): | |
return hash(tuple( | |
getattr(self.wrap, prop) if type(getattr(self.wrap, prop)).__hash__ != object.__hash__ else DeepComparator(getattr(self.wrap, prop)) | |
for prop in refineddir(self.wrap) | |
)) | |
def value(self): | |
return self.wrap | |
class Bar: | |
def __init__(self, x): | |
self.x = x | |
def __repr__(self): | |
return f"Bar({self.x})" | |
class Foo: | |
def __init__(self, a, b): | |
self.a = a | |
self.b = Bar(b) | |
def __repr__(self): | |
return f"Foo({self.a}, {self.b})" | |
data = (Foo(11, 22), Bar(-1), Foo(11, 22), Foo(11, -1), Foo(0, 22), Foo(0, 0)) | |
unique = tuple(map(DeepComparator.value, set(map(DeepComparator, data)))) | |
print(unique) | |
assert DeepComparator(Foo(11, 11)) == DeepComparator(Foo(11, 11)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment