在Python中的事件队列周围传递对象

Chr*_*s W 5 python

所以对于我正在处理的事情,我有一个相对复杂的设置,解释如下:

这是python。以及更多的粗略轮廓,但它涵盖了我需要的一切。尽管过程的下一个功能是相同的,但如果需要,请随时清理。

#timer event that runs every .1 second and processes events in a queue
some_event_timer():
    events.process_next()

class Event_queue:
    def __init__(self):
        self.events = []

    def push(self, event, parameters):
        self.events.insert(len(self.events), event, parameters)

    def process_next(self):
        event = self.pop(0)
        event[0](event[1])

class Foo:            
    def __init__(self, start_value = 1):
        self.value = start_value

    def update_value(self, multiple):
        self.value *= multiple

    def return_bah(self)
        return self.value + 3

class Bar:
    def __init__(self, number1, number2):
        self.init = number1
        self.add = number2

    def print_alt_value(self, in_value):
        print in_value * (self.init + self.add)
Run Code Online (Sandbox Code Playgroud)

这只是我所拥有的东西,但这说明了我的问题:执行以下操作

events2 = Event_queue2()
foo1 = Foo(4)   ----> foo1.value = 4 here
bar1 = Bar(4, 2)

events2.push(foo1.update_value,1.5)
events2.push(bar1.print_alt_value,foo1.value)
events2.push(bar.print_alt_value,foo1.return_bah())

events2.process_next() ----> should process update_value to change foo.value to 6
events2.process_next() ----> should process print_alt_value in bar class - expected 36
events2.process_next() ----> should process print_alt_value - expected 54
Run Code Online (Sandbox Code Playgroud)

我最初希望输出为36 6 *(4 + 2)

我知道为什么不这样做,foo1.value和foo1.return_bah()作为评估参数(正确的术语?)传递。我真正想要的是传递对变量的引用或对方法的引用,而不是在将其放入事件队列时对其求值。

谁能帮我。

我尝试搜索,但是无法拼凑出我想要的东西。为了获得我现在拥有的内容,我首先看了这些线程: 在Python中使用具有函数名称的字符串调用模块的函数

使用字符串在Python中调用函数

但是我看不到如何从中正确地支持参数,或者如何支持从中传递另一个函数或对变量的引用。

我想至少对于方法调用,我也许可以将参数传递为foo1.return.bah并在process_next方法中求值,但是我希望可以采用一种既可以接受标准变量又可以接受方法调用的通用方法,因为event_queue两者兼而有之。

感谢您的帮助

更新编辑:

因此,我遵循以下建议,并且非常接近,但是:

好的,所以我遵循了您的队列建议,并且非常接近我想要的内容,但是我不完全了解有关多功能的第一部分。

我也想以此来调用对象字典。例如:

names = ["test1", "test2"]
    for name in names:
        names_objs[name] = Foo(4)
Run Code Online (Sandbox Code Playgroud)

然后在尝试通过lambda推送时

for name in names_list:
    events2.push(lambda: names_objs[name].update_value(2))
Run Code Online (Sandbox Code Playgroud)

不起作用。实际上,当事件得到处理时,它只能在任何name_objs [name]引用上运行,并且如果name变量不再有效或已在函数外部被修改,那是错误的。这实际上并不奇怪,但是添加了:

name_obj_hold = name_objs[name] 
Run Code Online (Sandbox Code Playgroud)

然后也没有推动。它再次仅对最后引用的name_obj_hold起作用。

有人可以澄清多个funcs吗?恐怕我的头缠不住。

基本上,我需要对初始方法调用进行评估,因此类似:names_objs [name] .some_func(#something here#)获取正确的方法并与正确的类对象实例相关联,但是#here#something没有得到评估(无论是变量还是其他函数),直到它实际上从事件队列中被调用为止。

unh*_*ler 3

不要传入要调用的函数func1和应传递给该函数的参数,而是传入一个func2使用func1应传入的参数进行调用的函数。

d = {"a":1}
def p(val):
  print val

def func1():
  p(d["a"])

def call_it(func):
  func()

call_it(func1)
d["a"] = 111
call_it(func1)
Run Code Online (Sandbox Code Playgroud)

在 内func1d["a"]不进行评估,直到func1

出于您的目的,您的队列将更改为:

class EventQueue(object):
  def __init__(self):
    self.events = deque()
  def push(self, callable):
    self.events.append(callable)
  def process_next(self):
    self.events.popleft()()
Run Code Online (Sandbox Code Playgroud)

collections.deque从队列前面弹出的速度比列表更快。

要使用EventQueue,您可以使用 lambda 来实现快速匿名函数。

events2 = EventQueue()
foo1 = Foo(4)
bar1 = Bar(4, 2)

events2.push(lambda: foo1.update_value(1.5))
events2.push(lambda: bar1.print_alt_value(foo1.value))
events2.push(lambda: bar1.print_alt_value(foo1.return_bah()))

events2.process_next()
events2.process_next() # 36.0
events2.process_next() # 54.0
Run Code Online (Sandbox Code Playgroud)

对于编辑:

在这种情况下,您需要“捕获”范围比循环更严格的变量中的值。您可以使用普通函数partial()来实现这一点。

for name in names_list:
  def update(name):
    names_objs[name].update_value(2)
  events2.push(partial(update, name))
Run Code Online (Sandbox Code Playgroud)