Python、循环和闭包

Python、循环和闭包,python,function,closures,definition,Python,Function,Closures,Definition,我是一个相当有经验的C/C++程序员,在某种程度上是Java程序员。我正在学习python,但我对这种语言的一些奇怪的背景行为感到困惑 我正在学习嵌套函数和闭包,阅读学习Python,这对我来说似乎是一个很好的来源 我理解,如果在调用创建函数时在一个for循环中嵌套一个DEF,它会查找捕获的循环变量的最后一个值,因为它被引用捕获,因为C++程序员会把它放在 funcs = [] for i in range(4): def f(): print(i) funcs.

我是一个相当有经验的C/C++程序员,在某种程度上是Java程序员。我正在学习python,但我对这种语言的一些奇怪的背景行为感到困惑

我正在学习嵌套函数和闭包,阅读学习Python,这对我来说似乎是一个很好的来源

我理解,如果在调用创建函数时在一个for循环中嵌套一个DEF,它会查找捕获的循环变量的最后一个值,因为它被引用捕获,因为C++程序员会把它放在

funcs = []
for i in range(4):
    def f():
        print(i)
    funcs.append(f)
运行程序,结果是

>>> for f in funcs:
      f()


3
3
3
3
现在,我正聚精会神地思考这个问题,突然发现了一个对我来说似乎不一致的问题:如果我这样做了

for i in range(4):
  funcs[i]()


0
1
2
3
更令人困惑的是,如果我这样做的话

>>> i = 2
>>> funcs[i]()

2
现在,列表中的所有函数都返回2:

for f in funcs:
  f()


2
2
2
2
一定有一些与范围相关的问题,我无法理解您的功能

def f():
    print(i)
打印i的当前值

如果你写信

for i in range(4):
    funcs[i]()
for f in funcs:
    f()
然后在循环过程中,我被设置为0,1,2,3。这就是我在range4中的意思

如果你写信

for i in range(4):
    funcs[i]()
for f in funcs:
    f()

然后我继续使用它已有的任何值。

首先,这将创建一个包含四个函数的列表

funcs = []
for i in range(4):
  def f():
    print(i)
  funcs.append(f)
每个函数都会查找i的值,然后将其打印出来

这将遍历函数列表并调用每个函数:

>>> for f in funcs:
      f()
如上所述,这些函数查找i,现在是3,这是因为前面完成了range4中的for i循环,所以得到了4个3的打印输出

现在再次循环,使用i作为循环变量:

for i in range(4):
  funcs[i]()


0
1
2
3
第一次通过循环时,i是0,所以当函数查找i时,它得到0,然后打印它。然后变为1,然后变为2,然后变为3

以下代码只是以另一种方式更改i,并调用函数:

>>> i = 2
>>> funcs[i]()

2
你可以调用这些函数中的任何一个,它们仍然会打印出2,因为这就是i现在的值。你只是迷路了,因为你循环了range4来创建这些函数,然后你循环了range4来索引函数列表,你继续重用i,然后你重新分配i,并用它来索引列表

如果希望每个函数的打印值i固定为定义函数时的值,最简单的方法是使用默认参数,因为这些参数是在定义函数而不是调用函数时计算的:

funcs = []
for i in range(4):
  def f(num=i):
    print(num)
  funcs.append(f)

这里没有不一致。f中i的值取决于父范围中i的值。在运行range4中的第一个for i之后,我拥有范围中最后一个项的值,即3,因此对f的所有后续调用都将打印3

如果你跑

for i in range(4):
  funcs[i]()
在每个迭代步骤中重新定义i的值,得到0,1,2,3作为f打印的值。做


不会影响i的值,因此在所有函数调用中i的值都将为3

因为缩进错误,您第一次发布的代码无法按预期工作。抱歉,这是一个复制粘贴错误,我的代码是正确的,现在编辑它。我想您弄乱了funcs.appendf上的缩进。这里我可能有点不对劲,但printi将打印最后生成的内容。在您的例子中,这是针对range4:中的i,而不是在您定义函数时。因此,您获得输出并不奇怪。因此,我并没有冻结在函数创建上,但它是一个活生生的值。您正在打印i的最后一个已知/设置值。如果我在您编辑程序时运行该程序,则输出仅为一个“3”…我也无法重现第二个示例。请修复缩进并编写完整的代码,以便我们可以帮助您!