最近我开始玩Python,我遇到了一些特殊的闭包方式.请考虑以下代码:
adders=[0,1,2,3]
for i in [0,1,2,3]:
adders[i]=lambda a: i+a
print adders[1](3)
Run Code Online (Sandbox Code Playgroud)
它构建了一个简单的函数数组,它接受单个输入并返回由数字添加的输入.函数在for循环中构造,迭代器i从中循环0到3.对于这些数字中的每一个,lambda都会创建一个函数i,该函数捕获并将其添加到函数的输入中.最后一行将第二个lambda函数3作为参数调用.令我惊讶的是输出结果是6.
我期待一个4.我的理由是:在Python中,一切都是一个对象,因此每个变量都是指向它的指针.在创建lambda闭包时i,我希望它存储一个指向当前指向的整数对象的指针i.这意味着当i分配一个新的整数对象时,它不应该影响先前创建的闭包.遗憾的是,adders在调试器中检查数组表明它确实存在.所有的lambda功能指的最后一个值i,3,这将导致adders[1](3)返回6.
这让我想知道以下内容:
lambda函数以更改其值i时不会受到影响的方式捕获当前i值?我正在尝试在循环内创建函数并将它们存储在字典中.问题是字典中的所有条目似乎最终都映射到最后创建的函数.代码如下:
functions = []
for i in range(3):
def f():
return i
# alternatively: f = lambda: i
functions.append(f)
Run Code Online (Sandbox Code Playgroud)
这输出:
print([f() for f in functions])
# expected output: [0, 1, 2]
# actual output: [2, 2, 2]
Run Code Online (Sandbox Code Playgroud)
知道为什么吗?
我很惊讶这个断言失败了:
x = 42
x = lambda: x
assert x() == 42
Run Code Online (Sandbox Code Playgroud)
似乎x结束了递归指本身,这样x(),x()()等都是功能。
用于解析它的规则是什么,它记录在哪里?
顺便说一句(不出乎意料地给出了上面的内容), 的原始值x在 lambda 定义之后没有引用:
class X:
def __del__(self): print('deleting')
x = X()
x = lambda: x # 'deleting' is printed here
Run Code Online (Sandbox Code Playgroud) 我正在运行Python 3.4.2,我对代码的行为感到困惑.我正在尝试创建一个可调用多项式函数列表,其程度越来越高:
bases = [lambda x: x**i for i in range(3)]
Run Code Online (Sandbox Code Playgroud)
但出于某种原因,它做到了这一点:
print([b(5) for b in bases])
# [25, 25, 25]
Run Code Online (Sandbox Code Playgroud)
为什么bases看起来似乎是列表理解中最后一个lambda表达式的列表,重复?
这里发生了什么?我正在尝试创建一个函数列表:
def f(a,b):
return a*b
funcs = []
for i in range(0,10):
funcs.append(lambda x:f(i,x))
Run Code Online (Sandbox Code Playgroud)
这不符合我的期望.我希望列表的行为如下:
funcs[3](3) = 9
funcs[0](5) = 0
Run Code Online (Sandbox Code Playgroud)
但是列表中的所有函数似乎都是相同的,并且将固定值设置为9:
funcs[3](3) = 27
funcs[3](1) = 9
funcs[2](6) = 54
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
以下测试失败:
#!/usr/bin/env python
def f(*args):
"""
>>> t = 1, -1
>>> f(*map(lambda i: lambda: i, t))
[1, -1]
>>> f(*(lambda: i for i in t)) # -> [-1, -1]
[1, -1]
>>> f(*[lambda: i for i in t]) # -> [-1, -1]
[1, -1]
"""
alist = [a() for a in args]
print(alist)
if __name__ == '__main__':
import doctest; doctest.testmod()
Run Code Online (Sandbox Code Playgroud)
换一种说法:
>>> t = 1, -1
>>> args = []
>>> for i in t:
... args.append(lambda: i)
... …Run Code Online (Sandbox Code Playgroud) python closures list-comprehension generator-expression late-binding
def multipliers():
return [lambda x: i * x for i in range(4)]
print([m(1) for m in multipliers()]) # [3, 3, 3, 3]
Run Code Online (Sandbox Code Playgroud)
为什么不是[0, 1, 2, 3]?无法理解。那么,出于某种原因,我们i = 3在所有 lambda 表达式中都有?为什么?
我正在尝试生成(类似)以下字典:
funcs1 = {
'0':lambda x:x==0,
'1':lambda x:x==1,
'2':lambda x:x==2,
'3':lambda x:x==3,
'4':lambda x:x==4,
'5':lambda x:x==5,
}
Run Code Online (Sandbox Code Playgroud)
我尝试用这样的列表理解创建字典:
funcs2 = {str(i):lambda x:x==i for i in range(0,6)}
Run Code Online (Sandbox Code Playgroud)
或者只是使用for循环:
funcs3 = {}
for i in range(0,6):
funcs3.update({str(i): lambda x:x==i})
Run Code Online (Sandbox Code Playgroud)
但是,funcs2并且funcs3不一样funcs1,例如,当调用'0'每个元素并应用它时0,结果是不同的:
funcs1['0'](0)
Out[2]: True
funcs2['0'](0)
Out[3]: False
funcs3['0'](0)
Out[4]: False
Run Code Online (Sandbox Code Playgroud)
有人可以帮助我,并指出我在哪里犯了错误?