【问题标题】:Is there something like 'nonlocal' in Python < 3?Python < 3 中是否有类似“非本地”的东西?
【发布时间】:2012-03-25 02:05:26
【问题描述】:

我得到了这样一段代码:

foo = None

def outer():
    global foo
    foo = 0

    def make_id():
        global foo
        foo += 1
        return foo


    id1 = make_id() # id = 1
    id2 = make_id() # id = 2
    id3 = make_id() # ...

我觉得在最外层定义 foo 很难看,我宁愿只在 outer 函数中使用它。正如我正确理解的那样,在 Python3 中,这是由 nonlocal 完成的。对于我想要的东西,有没有更好的方法?我更愿意在outer 中声明和分配foo 并可能在inner 中声明global

def outer():
    foo = 0

    def make_id():
        global foo
        foo += 1     # (A)
        return foo

    id1 = make_id() # id = 1
    id2 = make_id() # id = 2
    id3 = make_id() # ...

(A) 不起作用,foo 似乎在最外层范围内搜索。

【问题讨论】:

    标签: python python-nonlocal


    【解决方案1】:

    我为此使用 1 元素列表:

    def outer():
        foo = [0]
        def make_id():
            r = foo[0]
            foo[0] += 1
            return r
        return make_id
    
    make_id = outer()
    id1 = make_id()
    id2 = make_id()
    ...
    

    这与使用nonlocal 相同,但语法稍显繁琐(foo[0] 而不是foo)。

    【讨论】:

    • 当我用函数属性解决了我原来的问题时,我没有尝试这个。但它看起来很有希望,我会记住这一点。
    【解决方案2】:

    不,将其作为make_id 函数的参数。最好将您的 id 放在一个类中,并将 make_id 作为实例方法,并将该实例作为全局方法(如果必须)。

    【讨论】:

    • 我也总是使用类来处理这种类型的行为;我认为这是一个更好的模式。
    • 我认为这是一个典型的“把课当作穷人的闭包”的例子。我更喜欢关闭。
    • @luispedro:不是这样。在这种情况下,将数据保留在函数中的尝试看起来像是穷人的对象系统。
    • 是的,闭包也是穷人的对象。我的观点是,它更像是一种风格。我觉得在这种情况下,关闭是一种更直接的意图表达。
    • @luispedro 我的观点不是闭包总是穷人的对象系统,而是这里的真实对象有潜在的好处,而闭包没有提供,例如在调用之间保持值外部函数。
    【解决方案3】:

    不,最好的选择是函数属性。

    【讨论】:

    • @Marcin 就像一个单独的对象或nonlocal 变量一样 - 你有多个闭包/函数对象/手动对象,要么将每个对象保留在一个线程上,要么需要同步.
    • @delnan 我的意思是,如果另一个线程进入 outer 会发生什么 - 大概,这将重置 outer.foo
    • @Marcin 不,这不是会发生什么。底层字节码是共享的,但每次执行def时,都会创建一个新的函数对象,每个对象都相互独立。
    • @delnan:等等,module 实例是线程本地的吗? (我对 python 线程一无所知)。
    • @Marcin modules 据我所知是全球性的。但是我们什么时候开始讨论模块了?我以为这是关于函数
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-30
    • 2021-09-29
    • 2016-10-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多