Luc*_*uca 2 python closures function definition
我是一个相当有经验的 C/C++(在某种程度上,Java)程序员。我正在学习 python,但我对这种语言的一些奇怪的(对于我的背景)行为感到困惑。
我正在学习嵌套函数和闭包(阅读“学习 Python”,这对我来说似乎是一个非常好的来源)。
我明白,如果我在调用创建的函数时将 def 嵌套在 for 循环中,它会查找捕获的循环变量的最后一个值(因为它是通过引用捕获的,就像 C++ 程序员所说的那样)
funcs = []
for i in range(4):
def f():
print(i)
funcs.append(f)
Run Code Online (Sandbox Code Playgroud)
并运行程序的结果是
>>> for f in funcs:
f()
3
3
3
3
Run Code Online (Sandbox Code Playgroud)
现在,当我偶然发现这个(在我看来)不一致时,我正在考虑这个问题:如果我这样做
for i in range(4):
funcs[i]()
0
1
2
3
Run Code Online (Sandbox Code Playgroud)
更莫名其妙,如果我这样做
>>> i = 2
>>> funcs[i]()
2
Run Code Online (Sandbox Code Playgroud)
现在,列表中的所有函数都返回 2:
for f in funcs:
f()
2
2
2
2
Run Code Online (Sandbox Code Playgroud)
一定有一些我无法理解的与范围相关的问题
Tig*_*kT3 10
首先,这将创建一个包含四个函数的列表。
funcs = []
for i in range(4):
def f():
print(i)
funcs.append(f)
Run Code Online (Sandbox Code Playgroud)
这些函数中的每一个都会查找 的值,i然后将其打印出来。
这会循环遍历函数列表并调用每个函数:
>>> for f in funcs:
f()
Run Code Online (Sandbox Code Playgroud)
如上所述,这些函数查找i,由于for i in range(4)之前完成的循环,现在为 3 ,因此您会得到 4 个 3 的打印输出。
现在再次循环,使用i循环变量:
for i in range(4):
funcs[i]()
0
1
2
3
Run Code Online (Sandbox Code Playgroud)
第一次通过循环,i是 0,所以当函数查找时i,它得到 0,然后打印出来。然后它变成 1,然后是 2,然后是 3。
下面的代码只是i以另一种方式进行了更改,并调用了一个函数:
>>> i = 2
>>> funcs[i]()
2
Run Code Online (Sandbox Code Playgroud)
你可以调用这些函数中的任何一个,它们仍然会打印 2,因为这是i现在的值。你只是迷路了,因为你循环range(4)创建这些函数,然后循环range(4)索引函数列表,然后继续重用i,然后重新分配i并使用它来索引列表。
如果您希望每个函数的打印值i固定为定义函数时的值,最简单的方法是使用默认参数,因为在定义函数时而不是在调用函数时计算这些值:
funcs = []
for i in range(4):
def f(num=i):
print(num)
funcs.append(f)
Run Code Online (Sandbox Code Playgroud)