python参数实际上是参数的别名吗? 请考虑下面的代码。 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]())

python参数实际上是参数的别名吗? 请考虑下面的代码。 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]()),python,function,parameters,arguments,alias,Python,Function,Parameters,Arguments,Alias,这是打印出来的 2 2 二, 从(最后一节)中的“别名的使用”和中的“范围”部分中,我了解到函数参数实际上是传递的参数的别名 那么根据这个,在 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 你能解释一下我做错了什么吗?感谢您在这里创建了一个闭包fun

这是打印出来的

2
2
二,

从(最后一节)中的“别名的使用”和中的“范围”部分中,我了解到函数参数实际上是传递的参数的别名

那么根据这个,在

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的实例在FOR循环执行时由DEF语句创建

然后在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
返回
func1
时,
i
已在
func1
中绑定,执行此操作时:

for i in range(3):
    def func2():
        return func1(i)
您正在为
[0,1,2]
中的每个
i
重新定义
func2
。生命的最终定义是:

def func2():
    return func1(2)

就这么简单。不幸的是,它的行为与您期望的不一样。

问题是Oooh的可能重复。所以你的意思是它和运行时i的对象被绑定到x(当然是另一个名称)有关?(当我打印值时?@NamanJain在您的代码中,
func1
的主体直到运行时才知道
I
。这是由于懒惰的评估。因此,在最后一次计算
func1(i)
func1
使用它为
i
找到的任何值,即2。但是“对于范围(3)中的i:def func2(k=i):返回func1(k)”呢?我尝试了这个,这个打印了0 1 2。@NamanJain很好,这很有效,因为您通过默认参数
k
引导
I
,由于作用域的原因,我通过正常参数进行了引导。除此之外,两者完全相同。@NamanJain你的结论几乎完全正确。只是与Haskell不同,Python可选地提供了这一极好的特性,即在使用闭包时。如果你像我一样广泛使用发电机,你会得到一种不同的味道,这是非常有效和美妙的。