有,雖然你必須寫它。一種可能性是創建一個descriptor,做基於instance.state
或任何選擇的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:
爲了支持方法調用,函數包括用於屬性訪問期間結合方法__get__()
方法。這意味着所有函數都是非數據描述符,它們返回綁定或未綁定的方法,具體取決於它們是從對象還是類調用。
在有狀態類,你可以創建一個調度員和註冊方法:
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)
讓我們來看看它在行動:
>>> 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
請注意,這是調度的一個非常邪惡的方法基於狀態,因爲對於未來的代碼讀者來說,整個機制將很難遵循。
調度文本狀態的另一種方法是在方法名稱中對狀態進行編碼,並根據調度函數中的選擇正確的方法。很多python類都使用這種模式(例如ast.NodeVisitor
):
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()
非常感謝您的支持。我真的不得不學習這個'描述符'魔術 –