1

我正在尝试了解 Python 3 变量范围和nonlocal.

考虑以下函数(这只是一个示例):

def build_property(something):

    def deco(func):

        def getter(self):
            return getattr(self, something)

        def setter(self, value):
            setattr(self, something, value)

        return property(getter, setter)

    return deco

没有nonlocal. 但是,如果现在我想根据something需要非本地有条件地创建 getter 和 setter。

def build_property(something):

    def deco(func):

        nonlocal something # This is needed

        if something.startswith('A'):
            getter = None
        else:
            def getter(self):
                return getattr(self, something)

        if something.startswith('B'):
            setter = None
        else:
            def setter(self, value):
                setattr(self, something, value)

        return property(getter, setter)

    return deco

为什么nonlocal在一种情况下需要,而在另一种情况下不需要?换句话说,为什么something如果在第一种情况下正确找到(没有nonlocal),但在第二种情况下我得到:“UnboundLocalError:在分配之前引用局部变量'某物'”如果nonlocal不存在?

4

2 回答 2

5

首先: nonlocal在您编写的代码中不是必需的。您不会更改something指向的对象。

第二:在某些情况下您需要使用nonlocal. 下面是一些nonlocal必要的代码。请注意,所有断言都是正确的(也就是说,它们不会引发 AssertionError)。

def main():
    variable = 1

    def function():
        variable = 2
    function()
    assert variable == 1

    def function():
        nonlocal variable
        variable = 2
    function()
    assert variable == 2

if __name__ == '__main__':
    main()

第三:您提供的代码不会产生您声称的错误。如果我删除该nonlocal行并调用以下函数,则不会出现错误。

build_property('A')(lambda: True)
build_property('B')(lambda: True)
build_property('C')(lambda: True)
于 2014-01-11T17:12:31.013 回答
-1
def A(d):
    outer = object()
    d["outer"] = outer
    def B():
        print locals()
        assert d["outer"] is outer #This fails and never reaches
        inner = object()
        d=dict()                   #this line.
        print locals()
    def C():
        print locals()
        assert d["outer"] is outer #This goes on fine.
        inner = object()
        print locals()
    return B,C

=> b,c = A(dict())
=> c()
-snip, AOK-
=> b()
UnboundLocalError: local variable 'd' referenced before assignment

对不起,我活该。上面的代码是我快速写出来的,让之前在这里的答案变成了一堆废话。

但这令人惊讶。我一直认为 python(2.x) 是一种完全没有远见的语言,在最后一刻评估一切......

对不起,现在是题外话。

于 2014-01-11T15:10:55.360 回答