在Python中定义函数列表

2024-04-26 00:32:38 发布

您现在位置:Python中文网/ 问答频道 /正文

Possible Duplicate:
Python lambdas and scoping

我希望0和3的函数会产生一个由1和3组成的常量:

lis = []
for i in range(3):
    lis.append( lambda: i )

但它们最终都取2值。我希望深度复制可以解决这个问题,但似乎行不通。在


Tags: andlambda函数inforrange常量append
2条回答

你可以循环以避免写这样的东西:

lis.append( lambda: 0 )
lis.append( lambda: 1 )
lis.append( lambda: 2 )

您的目的是编写返回常量整数的lambda函数。但是您定义并附加了一个返回object i的函数。因此,3个附加函数是相同的。在

创建的函数后面的字节码返回i

^{pr2}$

调用这些函数中的任何一个返回示例代码中i的最新值2

In [28]: lis[0]()
Out[28]: 2

如果删除i对象,则会出现一个错误:

In [29]: del i

In [30]: lis[0]()
                                     -
NameError                                 Traceback (most recent call last)
<ipython-input-30-c9e334d64652> in <module>()
  > 1 lis[0]()

<ipython-input-18-15df6d11323a> in <lambda>()
      1 lis = []
      2 for i in range(3):
  > 3     lis.append( lambda: i )

NameError: global name 'i' is not defined

解决方案可能是继续使用循环来编写包含所需常量的代码,并实际运行该代码:

In [31]: lis = []
    ...: for i in range(3):
    ...:     exec 'lis.append( lambda: {} )'.format(i)
    ...:  

结果如下:

In [44]: lis[0]()
Out[44]: 0

In [45]: lis[1]()
Out[45]: 1

In [46]: dis.dis(lis[0])
  1           0 LOAD_CONST               1 (0)
              3 RETURN_VALUE        

In [47]: dis.dis(lis[1])
  1           0 LOAD_CONST               1 (1)
              3 RETURN_VALUE        

@Boud给出了一个非常好的答案,解释了为什么你的代码不能像你期望的那样工作。重要的是,在lambda中引用i之前,必须计算它的值。下面是一个有点老套的方法:

lis = []
for i in range(3):
    lis.append( lambda i=i: i )

这使用了Python的默认函数参数值特性,例如在函数中可以写下:

^{pr2}$

现在,诀窍是在创建函数(方法、lambda表达式)时,将参数的默认值存储在该点。因此:

j = 10
def f(i=j):
    return i

j = 20
print( f(125) ) # no matter that j has been changed, the output is...
>>> 125

同样的伎俩也适用于lambda。为了更清楚一点:

lis = []
for j in range(3):
    lis.append( lambda i=j: i )

# Calling the lambdas
print(lis[1]())
>>> 1

相关问题 更多 >