python延迟加载模式在循环中使用最后一个值

时间:2019-07-01 07:56:03

标签: python scope closures lazy-loading

我想在一个循环中设置类方法。 这是我的示例代码:

class A:
    pass

def gen_func(k):
    return classmethod(lambda cls: k)

for k in ('m1', 'm2'):
    def gen_func2(k):
        return classmethod(lambda cls: k)
    setattr(A, 'resolve_%s'%k, classmethod(lambda cls: k))  # print result is: m2, m2
    # setattr(A, 'resolve_%s'%k, classmethod((lambda: lambda cls: k)()))  # print result is: m2, m2

    # setattr(A, 'resolve_%s'%k, gen_func2(k)) # print result is: m1, m2
    # setattr(A, 'resolve_%s'%k, gen_func(k))  # print result is: m1, m2 #OK#

print(A.resolve_m1()) # expected print --> m1
print(A.resolve_m2()) # expected print --> m2

预期结果将打印出m1,m2。

但是当我在循环作用域中生成方法时,k始终是最后一个:m2

我只知道这是scope的原因,如果我们在循环中使用该函数,则该函数会延迟执行。

我在循环作用域之外定义了gen_func,它起作用了。

但是我想知道确切的原因是什么。 在这种情况下,代码如何在计算机中执行。

我试图从书籍或网站上找到原因,但我对此一无所知。

1 个答案:

答案 0 :(得分:0)

谢谢@AndrejKesely

现在我知道它是什么了,您可以使用lambda编写:

python link

setattr(A, 'resolve_%s'%k, classmethod((lambda k: lambda cls: k)(k)))

这里是the introduction of js closures,其中有一些图片有助于理解关闭的过程:

  

这种范围对象的概念与C或C ++非常不同,在C或C ++中,局部变量存储在堆栈中。在JavaScript中,范围对象改为在堆中分配(或至少它们的行为是这样),因此即使函数已经返回,它们也可能保持分配状态。稍后再讨论。