python 转换库:如何将参数传递给转换?

python transitions library: How to pass argumnets to a transition?

在 github 上的 documentation 之后,尚不清楚如何创建参数化转换。

他们定义转换如

self.machine.add_transition(trigger='wake_up', source='asleep', dest='hanging out')

我想要类似的东西

self.machine.add_transition(trigger='wake_up_parameterized', source='asleep', dest='hanging out', ...)

其中 ... 以某种方式传递所需的参数 wake_up_parameterized 将需要。

用法是

batman.wake_up_parameterized(my_param1, my_param2)

Transitions 支持吗?

如果没有,我该如何解决这个问题?看起来很基本。

您参考的文档指出:

Sometimes you need to pass the callback functions registered at machine initialization some data that reflects the model's current state. Transitions allows you to do this in two different ways.

First (the default), you can pass any positional or keyword arguments directly to the trigger methods (created when you call add_transition() [...] You can pass any number of arguments you like to the trigger. There is one important limitation to this approach: every callback function triggered by the state transition must be able to handle all of the arguments. This may cause problems if the callbacks each expect somewhat different data.

改变状态时,可以在回调中进行工作。 transitions 提供了多种可以调用回调的场合。来自文档:

最常见的用例是根据传递的参数确定是否应进行转换。正确的回调位置是 conditions。如果要检查多个转换但数据预处理有点密集,则可以使用 prepare 代替。现在,我们假设只检查一个转换。

from transitions import Machine
import random


class Superhero:

    def world_is_in_danger(self, chocolate_bars, *args, **kwargs):
        return chocolate_bars < 3

    def business_hours(self, time, *args, **kwargs):
        return 9 < time < 17

    def restock(self, chocolate_bars, *args, **kwargs):
        new_stock = chocolate_bars + random.randrange(1, 4, 1)  # heroes cannot carry more than 3 bars at a time
        print(f"I am {self.state} and went to the store at {time}. The stock is now {new_stock}.")


hero = Superhero()
machine = Machine(model=hero, states=['resting', 'awake'], initial='resting')
machine.add_transition('call_for_help', 'resting', 'awake',
                       conditions=['world_is_in_danger', hero.business_hours],
                       after='restock')
hero.call_for_help(chocolate_bars=10, time=5)  # everything looks good
assert hero.state == 'resting'  # hero isn't moving a bit
hero.call_for_help(chocolate_bars=2, time=8)  # we are about to run out! but it's too early...
assert hero.is_resting()
hero.call_for_help(chocolate_bars=1, time=10, weather='sunny')  # someone must help us!
# >>> I am awake and went to the store at 10. The stock is now 3.
assert hero.is_awake()

如文档中所述,传递给触发器函数的每个参数都将传递给 所有 已注册的回调。注册回调的标准方法是在 add_transition 中传递它们。我们传递了两个 conditions 回调:一个作为字符串,这是执行此操作的标准方式,另一个作为函数引用。将回调作为字符串传递将假定我们的模型(我们的英雄)有一个方法(或在调用时将有一个方法)具有该名称。不必将函数引用分配给相关模型。我们还为 after 注册了一个回调,当转换已经完成时将被调用。如果我们在该回调中评估 hero.state,它已经设置为 awake。通过向我们的回调函数添加 *args**kwargs,我们确保回调足够灵活以处理不同数量的传递参数并且只考虑相关信息。