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

时间:2013-11-19 21:12:03

标签: 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)

这是我所拥有的准系统,但它说明了我的问题: 执行以下操作

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

我最初预计我的输出为36 6 *(4 + 2)

我知道为什么它不是,foo1.value和foo1.return_bah()作为一个评估参数传递(正确的术语?)。 我真正想要的是将引用传递给变量或方法的引用,而不是在我将它放入事件队列时进行评估。

任何人都可以帮助我。

我试着搜索,但我无法拼凑出我想要的东西。 为了得到我现在拥有的东西我最初看了这些线程: Calling a function of a module from a string with the function's name in Python

Use a string to call function in Python

但我不知道如何正确地支持参数或如何支持从那些传递另一个函数或引用变量。

我想至少在方法调用,我也许可以传递参数作为foo1.return.bah并在process_next方法评价,但我希望这将接受标准变量和方法调用的一般方法,如event_queue将同时使用。

感谢您的帮助

更新编辑:

所以我按照下面的建议,并且非常接近,但是:

好的,所以我按照你的队列建议,非常接近我想要的,但我不完全理解关于多个功能的第一部分。

我希望能够用这个来调用对象字典。 例如:

names = ["test1", "test2"]
    for name in names:
        names_objs[name] = Foo(4)

然后尝试通过lambda推送

for name in names_list:
    events2.push(lambda: names_objs[name].update_value(2))

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

name_obj_hold = name_objs[name] 

然后推动那也没有。它再次只能在最后引用的name_obj_hold上运行。

有人可以澄清多个功能的事情。我担心我的头很难缠绕它。

基本上我需要评估初始方法调用,所以类似于:     names_objs [name] .some_func(#something in here#) 得到适当的方法,并用合适的类对象实例相关联,但在这里的#something#不得到评估(无论它是一个变量或其它功能),直到它实际上从事件队列调用。

1 个答案:

答案 0 :(得分: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)

func1内,d["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()()

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

要使用EventQueue,您可以使用lambdas进行快速匿名功能。

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

编辑:

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

for name in names_list:
  def update(name):
    names_objs[name].update_value(2)
  events2.push(partial(update, name))