Python,循环和闭包

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)