2017-06-06 240 views
0

为什么这不起作用?如何在循环内定义函数

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) 

但它比前一种方法更为复杂。

+0

试一下'u [me] = callback()'? – asongtoruin

+0

你认为types.FunctionType可以帮助你吗? – Ptank

+1

你不*需要创建一个类。只要理解Python闭包在词法上与后期绑定行为有关。 –

回答

5

所有的函数都引用相同的变量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') } 
0

您正在循环中重新定义callback()。所以最新版本会起作用。我认为你应该使用基于类的方法。

+2

这是不正确的。 'u ['foo']'和'u ['bar']'不会是相同的函数句柄。 – acdr

2

首先,在你的榜样,u['foo']不应该在所有返回一个字符串,但一个功能句柄。 :)编辑:这句话不再相关。

二,您的功能callback使用me,从外部范围。如果您在外部范围中更改此值(在您的情况下为您的循环),则该函数的输出也会更改。

为了解决这个问题,您需要将me作为函数自身范围的一部分,例如,通过做:

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

我的错误,我在例子中忘了'()' – nowox

0

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

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'