Skip to content

Instantly share code, notes, and snippets.

@ryanhinkel
Last active November 2, 2021 10:47
Show Gist options
  • Save ryanhinkel/a4cb550b25d0a06e37572d909805fb8d to your computer and use it in GitHub Desktop.
Save ryanhinkel/a4cb550b25d0a06e37572d909805fb8d to your computer and use it in GitHub Desktop.
"""
In the following example, we can pretend that A and B are both classes that are provided by another framework or library
"""
class A:
cheetahs = "are fast"
def __getattr__(self, attr):
print("A is the getter")
if attr == "donuts":
return "are delicious"
class B:
elephants = "are large"
def __getattr__(self, attr):
print("B is the getter")
# B.__getattr__ will not be called because A does not delegate to it
if attr == "frenchtoast":
return "is filling"
class C(A, B):
def __init__(self):
self.data = {
"apples": "grow on trees",
"bees": "make honey",
}
def __getattr__(self, attr):
print("C is the getter")
if attr in self.data.keys():
return self.data[attr]
# A.__getattr__ will be called only if we check for it and call it explicitly
elif hasattr(super(), '__getattr__'):
return getattr(super(), attr)
else:
raise AttributeError
c = C()
print(c.apples) # will be satisfied by C.__getattr__
print(c.bees) # will be satisfied by C.__getattr__
print(c.cheetahs) # will be satisfied by A.cheetah
print(c.donuts) # will be satisfied by A.__getattr__
print(c.elephants) # will be satisfied by B.elephants
print(c.frenchtoast) # will dispatch first to C.__getattr__, then to A.__getattr__,
# and will return None because A does not call getattr on super,
# nor does it raise an attribute error.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment