Is it possible to inverse inheritance using a Python meta class? -
out of curiosity, i'm interested whether it's possible write meta class causes methods of parent classes have preference on methods of sub classes. i'd play around while. not possible override methods anymore. base class have call sub method explicitly, example using reference base instance.
class base(metaclass=invertedinheritance): def apply(self, param): print('validate parameter') result = self.subclass.apply(param) print('validate result') return result class child(base): def apply(self, param): print('compute') result = 42 * param return result child = child() child.apply(2)
with output:
validate parameter
compute
validate result
if care making lookups on instances go in reverse order (not classes), don't need metaclass. can override __getattribute__
:
class reverselookup: def __getattribute__(self, attr): if attr.startswith('__'): return super().__getattribute__(attr) cls = self.__class__ if attr in self.__dict__: return self.__dict__[attr] # using [-3::-1] skips topmost 2 base classes, reverselookup , object base in cls.__mro__[-3::-1]: if attr in base.__dict__: value = base.__dict__[attr] # handle descriptors if hasattr(value, '__get__'): return value.__get__(self, cls) else: return value raise attributeerror("attribute {} not found".format(attr)) class base(reverselookup): def apply(self, param): print('validate parameter') result = self.__class__.apply(self, param) print('validate result') return result class child(base): def apply(self, param): print('compute') result = 42 * param return result >>> child().apply(2) validate parameter compute validate result 84
this mechanism relatively simple because lookups on class aren't in reverse:
>>> child.apply <function child.apply @ 0x0000000002e06048>
this makes easy "normal" lookup doing on class instead of instance. however, result in confusion in other cases, if base class method tries access different method on subclass, method doesn't exist on subclass; in case lookup proceed in normal direction , possibly find method on higher class. in other words, when doing have sure don't methods on class unless you're sure they're defined on specific class.
there may other corner cases approach doesn't work. in particular can see jury-rigged descriptor handling; wouldn't surprised if weird descriptors __set__
, or more complicated descriptors make more intense use of class/object parameters passed __get__
. also, implementation falls on default behavior attributes beginning 2 underscores; changing require careful thought how it's going work magic methods __init__
, __repr__
.
Comments
Post a Comment