简体   繁体   English

了解Python 3中的非本地

[英]Understanding nonlocal in Python 3

I am trying to understand Python 3 variable scoping and nonlocal . 我试图了解Python 3变量作用域和nonlocal

Consider the following function (it is just an example): 考虑以下功能(仅作为示例):

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

This works fine without nonlocal . 没有nonlocal这可以正常工作。 But if now I want to conditionally create getters and setters depending on something I need nonlocal. 但是,如果现在我要有条件地创建依赖于getter和setter something ,我需要外地。

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

Why is nonlocal needed in one case, but not in the other? 为什么在一种情况下需要nonlocal ,而在另一种情况下却不需要? In other word, why something if correctly found in the first case (without nonlocal ), but in the second I get: "UnboundLocalError: local variable 'something' referenced before assignment" if nonlocal is not present? 换句话说,为什么something如果正确发现首例(不含nonlocal ),但在第二个我得到:“UnboundLocalError:赋值之前引用局部变量‘东西’”,如果nonlocal是不存在?

First: nonlocal is not necessary in the code you've written. 首先:在您编写的代码中, nonlocal不是必需的。 You're not changing the object that something points to. 您没有更改something对象指向的对象。

Second: There are cases where you would need to use nonlocal . 第二:在某些情况下,您需要使用nonlocal Below is some code where nonlocal is necessary. 以下是一些需要nonlocal代码的代码。 Note that all of the assertions are correct (That is, they do not raise an AssertionError). 请注意,所有断言都是正确的(也就是说,它们不会引发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()

Third: The code you've presented does not produce the error that you claim it does. 第三:您提供的代码不会产生您声称的错误。 If I remove the nonlocal line, and call the following functions, I get no errors. 如果删除nonlocal行,并调用以下函数,则不会出错。

build_property('A')(lambda: True)
build_property('B')(lambda: True)
build_property('C')(lambda: True)
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

I'm sorry, I deserve the flame. 对不起,我该当大火。 Above code I wrote up quickly, makes the answer that was previously here a bunch of nonsense. 上面的代码我很快就写了,使以前这里的答案很废话。

But it's surprising. 但这令人惊讶。 I always thought of python(2.x) as a completely foresight-less language, evaluating everything at the last moment... 我一直认为python(2.x)是一种完全没有先见之明的语言,在最后一刻对所有内容进行了评估...

Sorry for what now is off-topic. 抱歉,现在没有主题了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM