在 pytransitions 中处理多个对象
Handling multiple objects in pytransitions
https://github.com/pytransitions/transitions
我尝试使用文档中的 batman = NarcolepticSuperhero("Batman")
示例。
但是假设我们有 100 个蝙蝠侠要处理,我的方法是创建每个蝙蝠侠对象的列表并使用循环单独跟踪它们的状态。
IMO 这太天真了。
哪位大侠可以提出一些有效的解决方案。
谢谢
我觉得你的建议很合理。
heros = [NarcolepticSuperhero(f"Batman{i:02d}")
for i in range(100)]
然后循环遍历所有这些,
或者使用 while True:
循环休眠片刻
然后随机选择一个英雄。
无论哪种方式,你都会有一个英雄
你可以触发一些新的过渡。
假设所有 NarcolepticSuperheros
应该表现相同,我建议对所有 'batmen' 使用一个 Machine
而不是实例化 NarcolepticSuperhero
一百次。这样,您可以使用 Machine.dispatch
在所有模型上触发事件,而不是循环遍历超级英雄列表(尽管在幕后 Machine
也只是循环遍历模型列表)。我稍微压缩了提到的示例(所有转换都在一个列表中),删除了绑定到 NarcolepticSuperheros
的机器并引入了 SuperheroDen
。关于状态检查,您可以使用字典来跟踪当前有多少英雄处于什么状态。我在NarcolepticSuperhero
中添加了一个hero_log
,每次英雄改变状态时,它会先退出当前状态,然后以新状态登录。
from transitions import Machine
from collections import defaultdict
import random
class NarcolepticSuperhero(object):
hero_log = defaultdict(list)
def __init__(self, name):
self.name = name
self.kittens_rescued = 0
def update_journal(self):
self.kittens_rescued += 1
@property
def is_exhausted(self):
return random.random() < 0.5
@staticmethod
def change_into_super_secret_costume():
print("Beauty, eh?")
def log_out(self):
self.hero_log[self.state].remove(self)
def log_in(self):
self.hero_log[self.state].append(self)
class SuperheroDen(Machine):
states = ['asleep', 'hanging out', 'hungry', 'sweaty', 'saving the world']
transitions = [
['wake_up', 'asleep', 'hanging out'],
['work_out', 'hanging out', 'hungry'],
['eat', 'hungry', 'hanging out'],
['nap', '*', 'asleep'],
dict(trigger='distress_call', source='*', dest='saving the world', before='change_into_super_secret_costume'),
dict(trigger='complete_mission', source='saving the world', dest='sweaty', after='update_journal'),
dict(trigger='clean_up', source='sweaty', dest='asleep', conditions=['is_exhausted']),
['clean_up', 'sweaty', 'hanging out'],
]
def __init__(self):
super().__init__(model=[NarcolepticSuperhero('Clone warrior') for i in range(100)],
states=self.states,
transitions=self.transitions,
# tell each model to 'log_out' right before state change
before_state_change='log_out',
# and to 'log_in' right after
after_state_change='log_in',
initial='asleep')
# since our super heroes are asleep (and 'spawn' in their state), we have to log them in the first time
for model in self.models:
NarcolepticSuperhero.hero_log[self.initial].append(model)
machine = SuperheroDen()
# trigger event 'wake_up' on all models
machine.dispatch('wake_up')
assert len(NarcolepticSuperhero.hero_log['asleep']) == 0
assert len(NarcolepticSuperhero.hero_log['hanging out']) == 100
for i in range(10):
machine.models[i].work_out()
assert len(NarcolepticSuperhero.hero_log['hanging out']) == 90
assert len(NarcolepticSuperhero.hero_log['hungry']) == 10
assert machine.models[0] in NarcolepticSuperhero.hero_log['hungry']
https://github.com/pytransitions/transitions
我尝试使用文档中的 batman = NarcolepticSuperhero("Batman")
示例。
但是假设我们有 100 个蝙蝠侠要处理,我的方法是创建每个蝙蝠侠对象的列表并使用循环单独跟踪它们的状态。
IMO 这太天真了。
哪位大侠可以提出一些有效的解决方案。
谢谢
我觉得你的建议很合理。
heros = [NarcolepticSuperhero(f"Batman{i:02d}")
for i in range(100)]
然后循环遍历所有这些,
或者使用 while True:
循环休眠片刻
然后随机选择一个英雄。
无论哪种方式,你都会有一个英雄
你可以触发一些新的过渡。
假设所有 NarcolepticSuperheros
应该表现相同,我建议对所有 'batmen' 使用一个 Machine
而不是实例化 NarcolepticSuperhero
一百次。这样,您可以使用 Machine.dispatch
在所有模型上触发事件,而不是循环遍历超级英雄列表(尽管在幕后 Machine
也只是循环遍历模型列表)。我稍微压缩了提到的示例(所有转换都在一个列表中),删除了绑定到 NarcolepticSuperheros
的机器并引入了 SuperheroDen
。关于状态检查,您可以使用字典来跟踪当前有多少英雄处于什么状态。我在NarcolepticSuperhero
中添加了一个hero_log
,每次英雄改变状态时,它会先退出当前状态,然后以新状态登录。
from transitions import Machine
from collections import defaultdict
import random
class NarcolepticSuperhero(object):
hero_log = defaultdict(list)
def __init__(self, name):
self.name = name
self.kittens_rescued = 0
def update_journal(self):
self.kittens_rescued += 1
@property
def is_exhausted(self):
return random.random() < 0.5
@staticmethod
def change_into_super_secret_costume():
print("Beauty, eh?")
def log_out(self):
self.hero_log[self.state].remove(self)
def log_in(self):
self.hero_log[self.state].append(self)
class SuperheroDen(Machine):
states = ['asleep', 'hanging out', 'hungry', 'sweaty', 'saving the world']
transitions = [
['wake_up', 'asleep', 'hanging out'],
['work_out', 'hanging out', 'hungry'],
['eat', 'hungry', 'hanging out'],
['nap', '*', 'asleep'],
dict(trigger='distress_call', source='*', dest='saving the world', before='change_into_super_secret_costume'),
dict(trigger='complete_mission', source='saving the world', dest='sweaty', after='update_journal'),
dict(trigger='clean_up', source='sweaty', dest='asleep', conditions=['is_exhausted']),
['clean_up', 'sweaty', 'hanging out'],
]
def __init__(self):
super().__init__(model=[NarcolepticSuperhero('Clone warrior') for i in range(100)],
states=self.states,
transitions=self.transitions,
# tell each model to 'log_out' right before state change
before_state_change='log_out',
# and to 'log_in' right after
after_state_change='log_in',
initial='asleep')
# since our super heroes are asleep (and 'spawn' in their state), we have to log them in the first time
for model in self.models:
NarcolepticSuperhero.hero_log[self.initial].append(model)
machine = SuperheroDen()
# trigger event 'wake_up' on all models
machine.dispatch('wake_up')
assert len(NarcolepticSuperhero.hero_log['asleep']) == 0
assert len(NarcolepticSuperhero.hero_log['hanging out']) == 100
for i in range(10):
machine.models[i].work_out()
assert len(NarcolepticSuperhero.hero_log['hanging out']) == 90
assert len(NarcolepticSuperhero.hero_log['hungry']) == 10
assert machine.models[0] in NarcolepticSuperhero.hero_log['hungry']