Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 制造;“国家”;在过渡fsm包中“更多”;“有状态的”;_Python_Transitions - Fatal编程技术网

Python 制造;“国家”;在过渡fsm包中“更多”;“有状态的”;

Python 制造;“国家”;在过渡fsm包中“更多”;“有状态的”;,python,transitions,Python,Transitions,我正在使用一个非常有用的用于python的FSM工具。我想让美国更,嗯,有状态。。。因此,变量可以是状态的局部变量,并且在输入或离开状态时,它们的值会发生变化。我最终在机器中得到了相当多的实例变量——我真的希望这些值中的一些在状态中(例如,我在这种状态中呆了多久)。它们不是模型的属性,而是状态进展的属性 我想知道是否有“最好的方法”可以做到这一点?亚类状态 谢谢我不知道什么是“最佳方法”,但合理的方法取决于你想要实现什么。您可以a)子类状态、b)装饰初始化状态或c)手动初始化(子类)状态并将其传

我正在使用一个非常有用的用于python的FSM工具。我想让美国更,嗯,有状态。。。因此,变量可以是状态的局部变量,并且在输入或离开状态时,它们的值会发生变化。我最终在机器中得到了相当多的实例变量——我真的希望这些值中的一些在状态中(例如,我在这种状态中呆了多久)。它们不是模型的属性,而是状态进展的属性

我想知道是否有“最好的方法”可以做到这一点?亚类状态


谢谢

我不知道什么是“最佳方法”,但合理的方法取决于你想要实现什么。您可以a)子类状态、b)装饰初始化状态或c)手动初始化(子类)状态并将其传递给机器

A)如果每个状态都具有相同的属性,则可以按照建议对状态进行子类化:

import transitions.extensions.nesting as nesting


class CounterState(nesting.NestedState):

    def __init__(self, *args, **kwargs):
        super(CounterState, self).__init__(*args, **kwargs)
        self.entered = self.exited = 0

    def enter(self, event_data):
        self.entered += 1

    def exit(self, event_data):
        self.exited += 1

    def __str__(self):
        return "State {0} has been entered {1} times and exited {2} times".format(self.name, self.entered, self.exited)


class CounterMachine(nesting.HierarchicalMachine):

    @staticmethod
    def _create_state(*args, **kwargs):
        return CounterState(*args, **kwargs)

machine = CounterMachine(states=['A', 'B'], initial='A')

a = machine.get_state('A')
b = machine.get_state('B')

print(a) # >>> State A has been entered 0 times and exited 0 times
machine.to_B()
print(a) # >>> State A has been entered 0 times and exited 1 times
print(b) # >>> State B has been entered 1 times and exited 0 times
我在这里使用了
NestedMachine
,因为
\u create\u state
到目前为止在
Machine
中不可用更新:从版本
0.4.4
开始,它也可用于
机器

B)另一种方法涉及通过模型对启动状态对象进行一些修饰:

from transitions import Machine


class Model(object):

    def __init__(self):
        self.machine = Machine(model=self, states=['A', 'B'], initial='A', 
                               before_state_change='exit_state',
                               after_state_change='enter_state')
        # loop through all the states and attach attributes
        for state in self.machine.states.values():
            state.entered = 0
            state.exited = 0

    def enter_state(self):
        # retrieve the state object by name
        self.machine.get_state(self.state).entered += 1

    def exit_state(self):
        self.machine.get_state(self.state).exited += 1


def print_state(state):
    print("State {0} has been entered {1} times and exited {2} times".format(state.name, state.entered, state.exited))

m = Model()

a = m.machine.get_state('A')
b = m.machine.get_state('B')

print_state(a)
m.to_B()
print_state(a)
print_state(b)
C)在必须单独处理每个状态的情况下,您可以手动启动状态,并将实例传递给计算机,而不是传递名称:

from transitions import Machine, State


class TicketState(State):

    def __init__(self, name, tickets):
        super(TicketState, self).__init__(name)
        self.tickets = tickets


class Model(object):

    def __init__(self):

        # Using our own state
        a = TicketState('A', 10)

        # Setting tickets ourselves
        b = State('B')
        b.tickets = 3

        self.machine = Machine(self, states=[a, b], initial='A',
                               before_state_change='decrease_tickets')

    def tickets_left(self):
        return self.machine.get_state(self.state).tickets > 0

    def decrease_tickets(self):
        s = self.machine.get_state(self.state)
        s.tickets -= 1
        if s.tickets < 0:
            raise Exception('No Tickets left!')
        print("State {0} has {1} tickets left.".format(s.name, s.tickets))

m = Model()
m.to_B() # >>> State A has 9 tickets left.
m.to_A() # >>> State B has 2 tickets left.
从导入计算机,状态
类别票证状态(状态):
定义初始(自我、姓名、票证):
超级(票证状态,自我)。\uuuuu初始化\uuuuuuu(名称)
self.tickets=票
类模型(对象):
定义初始化(自):
#利用我们自己的国家
a=票证状态('a',10)
#自己订票
b=状态('b')
b、 门票=3张
self.machine=machine(self,states=[a,b],initial='a',
_state_change='reduce_tickets'之前)
def票据左(自身):
返回self.machine.get_状态(self.state).tickets>0
def减少_票据(自身):
s=self.machine.get_状态(self.state)
s、 门票-=1张
如果s.tickets<0:
引发异常(“没有票证了!”)
打印(“州{0}还有{1}张票证。”.format(s.name,s.tickets))
m=模型()
m、 到B()#>>>州A还有9张票。
m、 到_A()#>>>州B还有两张票。

当然,属性和名称的数量在这里可能有所不同。除了在状态更改之前使用机器回调
,您还可以在进入/退出时将
回调传递到
状态
对象,以便在转换期间单独处理每个状态。或者子类
State。如果您只需要一组不同的状态类型,如
TimedState
和/或
CounterState

则输入(self,event_data)
,这不是状态局部变量的常见解释。您所建议的是持久的变量:当您进入一个状态时,它仍然具有与上次相同的变量。通常,您将变量放入一个状态,以确保每次输入状态时它们都会被重新初始化,而此解决方案不会这样做。我不确定这是否是OP想要的,但我想我应该发表评论,因为这个建议完全把我引入了错误的道路。@DanHule:说得好。在转换中,状态实例是持久的。OP声明了“……当状态被输入或离开时,它们的值发生了变化。”这(可能是错误的)对我来说意味着这些不是范围/时间属性。对于本地/临时/作用域状态可能会有所帮助。您可以传递一个类或类路径,该类或类路径将用于在每次输入状态时初始化对象。