【问题标题】:Are python parameters actually aliases to arguments?python参数实际上是参数的别名吗?
【发布时间】:2016-04-16 06:22:08
【问题描述】:

请考虑下面的代码。

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(最后一节)中的“别名的使用”和http://gestaltrevision.be/wiki/python/functions_basics 的“范围”一节中,我了解到函数参数实际上是所传递参数的别名。

所以据此,在

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。

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

【问题讨论】:

    标签: python function parameters arguments alias


    【解决方案1】:

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

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

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

    【解决方案2】:

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

    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 返回func1 时, i 已经绑定在 func1 中。

    【讨论】:

    • 哦。所以你的意思是它与 i 在运行时绑定到 x (当然是不同的名称)的对象有关? (当我打印值时?)
    • @NamanJain 在您的代码中,func1 的主体直到运行时才知道i。这是由于惰性评估。因此,在要评估 func1(i) 的最后时刻,func1 使用它为 i 找到的任何值,即 2。
    • 但是'for i in range(3): def func2(k=i): return func1(k)'呢?我试过这个,这个打印了 0 1 2。
    • @NamanJain 好吧,这很有效,因为您通过默认参数i 引导k,而由于范围界定原因,我通过普通参数进行了此操作。除此之外,两者完全相同。
    • @NamanJain 您的结论几乎完全正确。只是与 Haskell 不同的是,Python 可选地提供了这个极好的特性,即在使用闭包时。如果你像我一样广泛使用生成器,你会得到不同的感觉,而且非常高效和美妙。
    【解决方案3】:

    当你这样做时:

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

    您正在为[0, 1, 2] 中的每个i“重新定义”您的func2。最终的定义是:

    def func2():
        return func1(2)
    

    就这么简单。不幸的是,它的行为与您的预期不同。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-15
      • 2018-09-30
      • 2023-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多