理解Python 3中的非本地语言

时间:2014-01-11 14:06:37

标签: python python-3.x scoping python-nonlocal

我正在尝试理解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如果在第一种情况下正确找到(没有nonlocal),但在第二种情况下我得到:“UnboundLocalError:局部变量'某些'在赋值之前被引用”如果{{1}不存在?

2 个答案:

答案 0 :(得分:2)

首先: 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)

答案 1 :(得分:-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)是一种完全没有前瞻性的语言,在最后一刻评估所有内容......

对不起现在的话题感到抱歉。