I have a metaclass and and class that both use __getattribute__ to intercept attribute calls. They look like this:
class B(type):
def __getattribute__ (self, name) :
print(f'hello {self}')
return super().__getattribute__(name)
class C(metaclass=B):
MY_ATTR = 'hello attr'
def __getattribute__ (self, name) :
print(f'hello {self}')
return super().__getattribute__(name)
This behaves as I intend:
C.MY_ATTR
# hello <class 'C'>
# 'hello attr'
C().MY_ATTR
# hello <C object at 0x10bcbbda0>
# 'hello attr'
Now I want to take that duplicate code from B and C and let it be inherited. Lucky I called them B and C and left room for A. Here we go:
class A:
def __getattribute__ (self, name) :
print(f'hello {self}')
return super().__getattribute__(name)
class B(type, A):
pass
class C(A, metaclass=B):
MY_ATTR = 'hello attr'
Unfortunately, this no longer behaves as before:
C.MY_ATTR
# 'hello attr'
C().MY_ATTR
# hello <C object at 0x10bcbbda0>
# 'hello attr'
I assume the problem is something around a MetaClass not being able to inherit from a regular class but I'm unsure. I'm also open to any other implementations (maybe not requiring a metaclass) of getting the same behaviour - though I also still want calls like C.MISSING to raise a AttributeError.
There are similar questions to this (e.g. Get attributes for class and instance in python) but they are slightly different and don't achieve what I'm trying to.
Thanks
Afirst, e.g.class B(A, type):?hello <class 'C'> __getattribute__ TypeError: expected 1 arguments, got 0