Es gibt, obwohl Sie es schreiben müssen. Eine Möglichkeit ist eine descriptor zu erstellen, die die Dispatching tut basierend auf instance.state
oder beliebigen state_attr
:
class StateDispatcher(object):
def __init__(self, state_attr='state'):
self.registry = {}
self._state_attr = state_attr
def __get__(self, instance, owner):
if instance is None:
return self
method = self.registry[getattr(instance, self._state_attr)]
return method.__get__(instance, owner)
def register(self, state):
def decorator(method):
self.registry[state] = method
return method
return decorator
https://docs.python.org/3/howto/descriptor.html#functions-and-methods:
Methodenaufrufe Zur Unterstützung der Funktionen gehören die __get__()
Verfahren zur Methoden während Attribut Zugriffs Bindung . Dies bedeutet, dass alle Funktionen Nicht-Datendeskriptoren sind, die gebundene oder ungebundene Methoden abhängig davon zurückgeben, ob sie von einem Objekt oder einer Klasse aufgerufen werden.
In Ihrer Stateful-Klasse können Sie dann einen Dispatcher erstellen und registrieren Methoden:
class StateMachine(object):
dispatcher = StateDispatcher()
state = None
@dispatcher.register('test')
def test(self):
print('Hello, World!', self.state)
@dispatcher.register('working')
def do_work(self):
print('Working hard, or hardly working?', self.state)
ist es in Aktion Lassen Sie sehen:
>>> sm = StateMachine()
>>> sm.state = 'test'
>>> sm.dispatcher()
Hello, World! test
>>> sm.state = 'working'
>>> sm.dispatcher()
Working hard, or hardly working? working
>>> sm.state = None
>>> sm.dispatcher()
Traceback (most recent call last):
...
File "dispatcher.py", line 11, in __get__
method = self.registry[getattr(instance, self._state_attr)]
KeyError: None
Hinweis, dass dies eine ziemlich böse Methode des Versands basierend auf dem Status, da für zukünftige Leser Ihres Codes der ganze Mechanismus schwer zu folgen sein wird.
Eine weitere Methode, Textstatus zu senden, besteht darin, den Status in Ihren Methodennamen zu codieren und auf dieser Grundlage in einer Dispatching-Funktion die richtige Methode auszuwählen. Viele Python-Klassen verwenden dieses Muster (ast.NodeVisitor
zum Beispiel):
class StateMachine(object):
def dispatch(self, *args, **kwgs):
getattr(self, 'do_{}'.format(self.state))(*args, **kwgs)
def do_new(self):
print('new')
def do_archive(self):
print('archive')
sm = StateMachine()
sm.state = 'new'
sm.dispatch()
sm.state = 'archive'
sm.dispatch()
Vielen viel für Antwort intresting. Ich muss wirklich diese "descriptor" Magie lernen –