Python关闭函数失去外部变量访问

我刚刚学会了python @ decorator,它很酷,但很快我发现我的修改代码出现了奇怪的问题。

def with_wrapper(param1):
    def dummy_wrapper(fn):
        print param1
        param1 = 'new'
        fn(param1)
    return dummy_wrapper

def dummy():
    @with_wrapper('param1')
    def implementation(param2):
        print param2

dummy()

我调试它,它抛出了在打印参数1异常

UnboundLocalError: local variable 'param1' referenced before assignment

如果我删除了param1 = 'new'这一行,而没有对外部变量的变量进行任何修改操作(链接到新对象),这个例程可能会起作用。

这是否意味着我只做了一个外部范围变量的副本,然后进行修改?


感谢德尔南,关键是必不可少的。 从这里可能回答:与X语言关闭相比,Python中的闭包有哪些限制?

类似的代码:

def e(a):
    def f():
        print a
        a = '1'
    f()
e('2')

而且这也是以前令人讨厌的全球变数:

a = '1'
def b():
    #global a
    print a
    a = '2'
b()

这通过添加全局符号来解决。 但是关闭,没有找到这样的符号。 感谢unutbu,Python 3给了我们非本地的。

我知道从上面直接访问外层变量是只读的。 但是看到前面的阅读变量(print var)也受到影响会感到不舒服。


当Python解析一个函数时,它会在每次找到一个赋值左侧的变量时记录下来,例如

param1 = 'new'

它假设所有这些变量都是该函数的局部变量。 所以当你在这个任务之前

print param1

发生错误是因为在print语句执行时,Python没有为这个局部变量赋值。


在Python3中,你可以通过声明param1非本地来解决这个问题:

def with_wrapper(param1):
    def dummy_wrapper(fn):
        nonlocal param1
        print param1
        param1 = 'new'
        fn(param1)
    return dummy_wrapper

在Python2中,你必须使用一种技巧,例如在列表(或其他可变对象)中传递param1:

def with_wrapper(param1_list):
    def dummy_wrapper(fn):
        print param1_list[0]
        param1_list[0] = 'new'   # mutate the value inside the list
        fn(param1_list[0])
    return dummy_wrapper

def dummy():
    @with_wrapper(['param1'])   # <--- Note we pass a list here
    def implementation(param2):
        print param2

您可以在函数中分配param1 ,这使param1成为局部变量。 但是,它在打印时尚未分配,因此出现错误。 Python不会回退寻找外部作用域中的变量。


方便临时情况或探索性代码(但不是很好的做法)

如果你想在Python 2.x中从外部范围捕获一个变量,那么使用全局也是一个选择(通常的附带条件)。

虽然下面的内容会抛出(在inner内部赋值outer1使得它在本地,因此在if条件下是无界的):

def outer():
    outer1 = 1
    def inner():
        if outer1 == 1:
            outer1 = 2
            print('attempted to accessed outer %d' % outer1)

这不会:

def outer():
    global outer1
    outer1 = 1
    def inner():
        global outer1
        if outer1 == 1:
            outer1 = 2
            print('accessed outer %d' % outer1)
链接地址: http://www.djcxy.com/p/51251.html

上一篇: Python closure function losing outer variable access

下一篇: Python closure with side