如何在循环中定义函数

时间:2017-06-06 08:53:51

标签: python function-pointers

为什么这不起作用?

u = {}
for me in ['foo', 'bar']:
   def callback():
       return 'I am %s' % me
   u[me] = callback

我得到的输出是:

>>> u['foo']()
'I am bar'

似乎callback在最近的迭代中定义了一次。

编辑

正如kawadhiya21所提出的,课堂方法可行:

class CallbackFactory():
    def __init__(self, me):
       self.me = me

    def __call__(self):
       return 'I am %s' % self.me

u = {}
for me in ['foo', 'bar']:

   u[me] = CallbackFactory(me)

但它比前一种方法复杂得多。

4 个答案:

答案 0 :(得分:8)

您的所有函数都引用相同的变量me。当您尝试调用该函数时,me的值为'bar',因为它是循环结束时的内容。

如果希望me为函数的每个定义采用不同的值,则每个函数都需要自己的变量副本。

u = {}
for me in ['foo', 'bar']:
   def callback(me_copy=me):
       return 'I am %s' % me_copy
   u[me] = callback

如果您愿意,可以将其缩短为:

u = {}
for me in ['foo', 'bar']:
   u[me] = lambda me_copy=me: 'I am %s'%me_copy

甚至

u = { me: (lambda me_copy=me: 'I am %s'%me_copy) for me in ('foo', 'bar') }

答案 1 :(得分:2)

首先,在您的示例中,u['foo']根本不应返回字符串,而应返回函数句柄。 :)编辑:这句话不再相关。

其次,您的函数callback使用来自外部作用域的me。如果在外部范围中更改此值(在您的情况下是循环),则函数的输出也会更改。

要解决此问题,您需要将me部分功能作为自己的范围,例如通过做:

def callback(int_me=me):
    return 'I am %s' % int_me

答案 2 :(得分:1)

你想要定义一系列回调,而不是简单地保存一堆输出,对吧?定义一个绑定所需参数的函数,如下所示:

def make_callback(param):
    def callback():
       return 'I am %s' % param
    return callback

for me in ['foo', 'bar']:
    u[me] = make_callback(me)

>>> u["foo"]()
'I am foo'

答案 3 :(得分:0)

每次在循环中重新定义回调()。所以最新版本可行。我认为你应该使用基于类的方法。