Sie können Pythons kooperatives Mehrfachvererbungssystem wahrscheinlich verwenden, um Ihre Mixinklassen zu schreiben, anstatt zu versuchen, sie als Klassen-Dekoratoren zu implementieren. So habe ich generell den Begriff "Mixin" verstanden, der in Python OOP verwendet werden soll.
class Base:
def method(self, param):
value = param + 18
return value
class FeatureOne: # this could inherit from Base
def method(self, param):
if param == 42:
return 13
else:
return super().method(param) # call next class in inheritance chain
class Child(FeatureOne, Base):
def method(self, param):
value = super().method(param)
value *= 2
return value
Dies ist nicht ganz das gleiche wie das, was Sie wollten, da es die FeatureOne
Klasse ruft method
Umsetzung zwischen den Base
und Child
Klassen Versionen, anstatt vor Child
macht seine Sache. Sie könnten stattdessen eine neue Grandchild
Klasse hinzufügen, die von den Feature
s, die Sie zuerst interessieren, und Child
zuletzt erbt, wenn Sie die Methoden nicht anpassen können, um in dieser Reihenfolge zu arbeiten (der Körper der Grandchild
könnte leer sein).
Wenn Sie wirklich Dekoratoren verwenden möchten, um die Reihenfolge umzudrehen, denke ich, dass Sie es wahrscheinlich funktionieren lassen könnten, wenn der Dekorator eine "Enkel" -Klasse für Sie erstellt (obwohl er nichts über die normale Vererbungshierarchie weiß)). Hier ist ein grober Versuch eines mixin
Dekorateur, die fast wie Sie arbeiten will:
def mixin(*mixin_classes, **mixin_kwargs): # decorator factory function
def decorator(cls): # decorator function
class wrapper(*mixin_classes, cls):
def __init__(self, *args, **kwargs):
wrapped_kwargs = mixin_kwargs.copy() # use the passed kwargs to update the
wrapped_kwargs.update(kwargs) # mixin args, so caller can override
super().__init__(*args, **wrapped_kwargs)
# maybe modify wrapper's __name__, __qualname__, __doc__, etc. to match cls here?
return wrapper
return decorator
Die mixin Klassen super().__init__(*args, **kwargs)
aus ihrer eigenen __init__
Methode aufrufe sollen (wenn sie eine haben), aber sie können annehmen (und nicht weitergeben) keyword-nur Argumente ihrer eigenen, dass sie vom mixin
Dekorateur übergeben werden sollen:
class FeatureOne:
def __init__(self, *args, foo, **kwargs): # note that foo is a keyword-only argument
self.foo = foo
super().__init__(*args, **kwargs)
def method(self, param):
if param == self.foo:
return 13
else:
return super().__method__(param)
@mixin(FeatureOne, foo=42)
class Child(Base):
def method(self, param):
return super().method(param) * 2
der Dekorateur soll entweder arbeiten mit allen mixin Klassen zu einem Dekorateur Aufruf übergeben (zB @mixin(FeatureA, FeatureB, FeatureC, foo=42, bar=13, foobar=546)
) oder mit mehreren verschachtelten Dekorateur Anrufe. Die MRO der letzten Klasse werden auf beide Arten gleich sein.
Ich dachte über kooperative Vererbung nach und aktualisierte die Frage. Wie Sie bereits sagten, besteht das Problem darin, dass Funktionen das Verhalten der Unterklasse umbrechen. Vielleicht kann kooperative Vererbung mit einem '@ Mixin'-Dekorateur kombiniert werden? Eine andere Idee wäre, das Wrapping-Feature-Class-Objekt zu kopieren und die Wrapped-Sub-Klasse zu seinem '__bases__' hinzuzufügen. Denkst du, das könnte funktionieren? – danijar