python 参数实际上是参数的别名吗?

Are python parameters actually aliases to arguments?

请考虑以下代码。

a = []

def func1(x):
    return x

for i in range(3):
    def func2():
        return func1(i)

    a.append(func2)

for k in range(3):
    print(a[k]())

这打印出来

2
2
2

http://gestaltrevision.be/wiki/python/aliases (last section) and in 'Scope' section in http://gestaltrevision.be/wiki/python/functions_basics中的'The use of aliases',我了解到函数参数实际上是传递的参数的别名。

所以根据那个,在

def func1(x): return x

for i in range(3):
    def func2(): return func1(i)

我推断 x 将作为 i 的别名存储,即使每次执行循环时 i 都被重新分配,它的别名 x 也无关紧要。

所以我希望前三行输出 0、1、2 而不是 2、2、2。

你能解释一下我做错了什么吗?谢谢

您在此处创建一个闭包 func2,它使用封闭范围中的变量 i。 func2 的实例由 DEF 语句在 FOR 循环执行时创建。

然后在 FOR 循环退出后执行 func2。 在 python 中,循环变量在循环退出后不会被销毁。 因此,您的闭包在退出循环时使用封闭范围内 i 的当前值。

所以在这段代码中 func1 没有任何改变,没有它的结果是一样的。

如果您希望您的代码按您希望的方式工作,请执行以下操作

def func2(i): 
    def func1():
        return i
    return func1

a = [func2(i) for i in range(3)]
for k in range(3): 
    print(a[k]()) # prints 0 1 2

现在,为什么您的代码不起作用?好吧,这与对象何时绑定到闭包中的名称有关,func1 就是这样。在您的代码中,参数 xfunc1 在运行时被绑定。因此,由于 a 中的每个函数都有 func1(i) 并且 i 在打印时的值为 2,所以你得到所有 2。因此解决方案是在编译时绑定它,即当 func2 returns func1, i 已经绑定在 func1.

当你这样做时:

for i in range(3):
    def func2():
        return func1(i)

[0, 1, 2] 中每 i 个,你就是 "redefining" 你的 func2。 lives的最终定义是:

def func2():
    return func1(2)

就这么简单。不幸的是,它的行为并不像您期望的那样。