【问题标题】:Implementing a state machine with decorators使用装饰器实现状态机
【发布时间】:2015-10-01 22:04:02
【问题描述】:

在学习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

所以状态机所做的就是检查我当前的状态是否是请求的状态,如果是,它应该调用底层函数,最后它应该进一步设置状态。

你将如何实现它?

【问题讨论】:

  • 您是否尝试过实现它?发生了什么?你在哪里卡住了?请注意,CoffeeState 必须在您尝试应用Statemachine 之前 定义。

标签: python python-3.x decorator state-machine python-decorators


【解决方案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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-19
    • 1970-01-01
    相关资源
    最近更新 更多