python 初探狀態機transitions庫
阿新 • • 發佈:2019-01-30
接著繼續在add_model()中:
for trigger, _ in self.events.items():
self._add_trigger_to_model(trigger, model)
這個是遍歷我們Machine例項中的self.events的鍵值對,拿到每個觸發名字:to_liquid, to_solid, to_gas, to_plasma, melt, ionize, sublimate, evaporate,遍歷呼叫self._add_trigger_to_model(trigger, model):其實這個還是給model繫結偏函式,以後我們就能這麼呼叫model.melt()。def _add_trigger_to_model(self, trigger, model): trig_func = partial(self.events[trigger].trigger, model) setattr(model, trigger, trig_func)
所以到了這裡我們Machine例項關於model引數如下:
model.trigger("xxx")
model.to_liquid()
model.to_solid()
model.to_gas()
model.to_plasma()
model.melt()
model.mionize()
model.sublimate()
model.evaporate()
接著繼續在add_model()中:和上面差不多,遍歷呼叫_add_model_to_state(state, model)for _, state in self.states.items(): self._add_model_to_state(state, model)
def _add_model_to_state(self, state, model):
setattr(model, 'is_%s' % state.name,
partial(self.is_state, state.name, model))
所以到了這裡我們Machine例項關於model引數如下:好了,我們知道了model現在多了很多函式和屬性。model.is_solid model.is_liquid model.is_gas model.is_plasms model.state # 這個是model.setState()把初始化狀態如solid設定過來生成的屬性
好的,現在我們具體來看看呼叫model.melt()到底發生了什麼呢?它其實是呼叫self.events['melt'].trigger(model),
好的,看看self.events['melt'].trigger(model)裡面是啥?
def trigger(self, model, *args, **kwargs):
f = partial(self._trigger, model, *args, **kwargs)
return self.machine._process(f)
好的,原來是呼叫self.events['melt']._trigger(model),那麼這個實際處理函式_trigger()裡面又是啥呢? state = self.machine.get_state(model.state)
if state.name not in self.transitions:
msg = "%sCan't trigger event %s from state %s!" % (self.machine.name, self.name,
state.name)
if state.ignore_invalid_triggers:
logger.warning(msg)
return False
else:
raise MachineError(msg)
第一句就先找出當前model的狀態是什麼:<State('solid')@4372239248>.然後判斷state.name 在不在 當前event的transitions中:{'solid': [<Transition('solid', 'liquid')@4372347728>]}
好吧,確實存在,那麼就不用if語句塊啦。_trigger()繼續往下:
event_data = EventData(state, self, self.machine, model, args=args, kwargs=kwargs)
這個生成一個event_data例項,顧名思義,它就是一放資料的,裡面放了當前machine,當前state,當前event,當前的model,transitions,執行transition()的結果result,當然不僅僅是放資料而已,它還會update(),更新machine狀態。好吧,_trigger()繼續往下: for t in self.transitions[state.name]:
event_data.transition = t
if t.execute(event_data):
event_data.result = True
break
如上我們的self.transitions['solid']只有一個元素t:{'solid': [<Transition('solid', 'liquid')@4372347728>]},把這個元素t賦值給event_data後,開始執行t,等會執行結果還是要放到event_data中呢。總結下,到這裡我們執行model.melt(),其實就是執行self.events['melt'].transitions['solid'].execute().
好的,那我們繼續看看這個t.execute(event_data)怎麼個執行法。
因為我們沒帶什麼prepare, conditions等高階引數,所以我們把這個execute()簡化成:
def execute(self, event_data):
self._change_state(event_data)
return True
好吧,繼續看看transition._change_state(),顧名思義,它就是專門處理狀態的更新: def _change_state(self, event_data):
event_data.machine.get_state(self.source).exit(event_data)
event_data.machine.set_state(self.dest, event_data.model)
event_data.update(event_data.model)
event_data.machine.get_state(self.dest).enter(event_data)
沒什麼好說的,就是單純的處理前狀態"solid"的exit(),把當前狀態置成desc的狀態="liquid", 返回True。總結下,Machine就是有兩個self.events={}, self.states=[]輔助圍著self.model轉,維護好這個model的狀態,即可!
這個transitions庫大量運用偏函式呀和動態生成屬性函式什麼的,不過這也正常,畢竟從demo上看來,demo越簡單,底下的操作越複雜。
以上