-2

При изучении концепций декораторов в python я пришел к вопросу, если можно использовать декораторы для имитации конечного автомата.Реализация государственной машины с декораторами

Пример:

from enum import Enum 


class CoffeeMachine(object): 
    def __init__(self): 
     self.state = CoffeeState.Initial 

    #@Statemachine(shouldbe, willbe) 
    @Statemachine(CoffeeState.Initial, CoffeeState.Grounding) 
    def ground_beans(self): 
     print("ground_beans") 

    @Statemachine(CoffeeState.Grounding, CoffeeState.Heating) 
    def heat_water(self): 
     print("heat_water") 

    @Statemachine(CoffeeState.Heating, CoffeeState.Pumping) 
    def pump_water(self): 
     print("pump_water") 


class CoffeeState(Enum): 
    Initial = 0 
    Grounding = 1 
    Heating = 2 
    Pumping = 3 

Так что все StateMachine делает это, чтобы проверить мое текущее состояние запрашиваемых один, если он есть, он должен вызвать основную функцию и, наконец, она должна установить состояние дальше.

Как вы это реализуете?

+1

Вы сделали любую попытку осуществить? Что случилось? Где вы застряли? Обратите внимание, что 'CoffeeState' должен быть определен * до *, вы пытаетесь применить« Statemachine ». – jonrsharpe

ответ

1

Конечно, вы можете, если ваш декоратор делает предположение о том, где хранится состояние:

from functools import wraps 


class StateMachineWrongState(Exception): 
    def __init__(self, shouldbe, current): 
     self.shouldbe = shouldbe 
     self.current = current 
     super().__init__((shouldbe, current)) 


def statemachine(shouldbe, willbe): 
    def decorator(f): 
     @wraps(f) 
     def wrapper(self, *args, **kw): 
      if self.state != shouldbe: 
       raise StateMachineWrongState(shouldbe, self.state) 
      try: 
       return f(self, *args, **kw) 
      finally: 
       self.state = willbe 
     return wrapper 
    return decorator 

Декоратор рассчитывает получить self прошли в; то есть его следует применять к методам в классе. Затем он ожидает, что self будет иметь атрибут state для отслеживания состояния конечного автомата.

Демо:

>>> cm = CoffeeMachine() 
>>> cm.state 
<CoffeeState.Initial: 0> 
>>> cm.ground_beans() 
ground_beans 
>>> cm.state 
<CoffeeState.Grounding: 1> 
>>> cm.ground_beans() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 6, in wrapper 
__main__.StateMachineWrongState: (<CoffeeState.Initial: 0>, <CoffeeState.Grounding: 1>) 
>>> cm.heat_water() 
heat_water 
>>> cm.pump_water() 
pump_water 
>>> cm.state 
<CoffeeState.Pumping: 3>