Ja, Sie können Ihre eigene Klasse schreiben, die von stammt, wenn Sie möchten. Es ist ein bisschen kompliziert, obwohl. Sie müssen das Deskriptorprotokoll implementieren (Überschreiben der -Implementierung von), sodass es eine Instanz einer anderen benutzerdefinierten Klasse zurückgibt, die sich wie ein gebundenes Methodenobjekt verhält. Leider können Sie nicht von Pythons eingebautem gebundenem Methodentyp erben (ich bin nicht sicher, warum nicht).
Wahrscheinlich ist der beste Ansatz dann, eines der normalen Methodenobjekte in eine Instanz einer benutzerdefinierten Klasse zu verpacken. Ich bin mir nicht sicher, wie viel von der Methoden-API du replizieren musst, damit das ein wenig kompliziert wird. (Benötigen Sie Ihre Staaten, um miteinander vergleichbar zu sein? Müssen sie hashable? Pickable?)
Wie auch immer, hier ist eine nackte Knochen-Implementierung, die die minimale Menge notwendig, um eine Arbeitsmethode (plus die neue repr
):
class MethodWrapper:
def __init__(self, name, method):
self.name = name if name is not None else repr(method)
self.method = method
def __call__(self, *args, **kwargs):
return self.method(*args, **kwargs)
def __repr__(self):
return self.name
class State(classmethod):
def __init__(self, func):
self.name = None
super().__init__(func)
def __set_name__(self, owner, name):
self.name = "{}.{}".format(owner.__name__, name)
def __get__(self, owner, instance):
method = super().__get__(owner, instance)
return MethodWrapper(self.name, method)
Und eine schnelle Demo davon in Aktion:
>>> class Foo:
@State
def foo(cls):
print(cls)
>>> Foo.foo
Foo.foo
>>> Foo.foo()
<class '__main__.Foo'>
>>> f = Foo()
>>> f.foo()
<class '__main__.Foo'>
Beachten sie, dass die __set_name__
Verfahren durch den State
Descriptor verwendet nur von Python 3.6 genannt wird. Ohne dieses neue Feature wäre es für den Deskriptor viel schwieriger, seinen eigenen Namen zu lernen (Sie müssen möglicherweise eine Dekorator-Factory erstellen, die den Namen als Argument verwendet).
Was ist der Grund, diese Klassenmethoden zu machen? Es macht 'EntityBlock' effektiv zu einem Singleton, aber selbst wenn Sie nur eine Instanz erstellen, scheint es komplexer zu sein. Insbesondere wenn Sie niemals Instanzen erstellen, wird '__init__' niemals aufgerufen. Wenn Sie Instanzen erstellen, teilen sie sich den Status, was weniger nützlich erscheint. – cco
Dies ist ein minimales Beispiel. EntityBlock wird erstellt, andernfalls hätte es kein '__init__' ... Nein, sie teilen keinen Zustand, weil der" Zustand "die Methode und nicht die Klasse ist. Die Klasse ist eine Gruppe von Zuständen in einer hierarchischen Zustandsmaschine. Jedenfalls beantwortet es meine Frage nicht, oder? – Paebbels
Rechts. Mein Kommentar ist nicht auf Ihre Frage gerichtet, ich reagierte nur auf etwas, das mir seltsam erschien. – cco