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
就是这样。在您的代码中,参数 x
到 func1
在运行时被绑定。因此,由于 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)
就这么简单。不幸的是,它的行为并不像您期望的那样。
请考虑以下代码。
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
就是这样。在您的代码中,参数 x
到 func1
在运行时被绑定。因此,由于 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)
就这么简单。不幸的是,它的行为并不像您期望的那样。