【问题标题】:Does Python provide a way to access a variable beyond the nearest enclosing scope?Python 是否提供了一种访问最近封闭范围之外的变量的方法?
【发布时间】:2021-10-16 02:02:41
【问题描述】:

鉴于下面的示例,灵感来自SO Question

x = 0
def func1():
    x = 1
    def func2():
        x = 2
        def func3():
            KEYWORD x # scope declaration
            x = 3
        func3()
    func2()
func1()

globalnonlocal 作为关键字,对于x,值分别是02,而不是3

Python 是否提供了一种机制来在func3() 中使用func1() 的范围为x?还是只能在此处访问 globalfunc2func3 范围?

【问题讨论】:

    标签: python python-3.x scope


    【解决方案1】:

    不,您不能使用nonlocal 指定特定范围。它总是会选择最近的包含命名变量的封闭范围。

    由于 Python 使用词法作用域,因此进入这种情况的唯一方法是自己编写所有作用域的代码。 (例如,当您编写func3 时,您知道它嵌套在func2 中,因此您知道func2 范围内的所有变量。)只是不要在编写代码时的每个作用域,nonlocal 都会做正确的事情。 (我们将首先忽略编写如此深度嵌套的代码的问题。)

    x_global = 0
    def func1():
        x_first = 1
        def func2():
            x_second = 2
            def func3():
                nonlocal x_first # scope declaration
                x_first = 3
            func3()
        func2()
    func1()
    

    相比之下,让我们假设 Python 使用了动态作用域。

    x = 9
    
    def func1():
        nonlocal x
        x = 3
    
    def func2():
        x = 1
        func1()
        print(x)
    
    def func3():
        print(x)
    
    func2()    # Prints 3
    print(x)   # Prints 9; the global variable hasn't been changed
    func1()
    print(x)   # Prints 3; the global variable *has* changed.
    

    func1 修改的变量现在取决于调用func1 的范围。

    在真正的 Python 中,上面的序列会打印出来

    1
    3
    3
    

    因为func1总是修改全局变量,无论是从全局范围调用还是从func2 的本地范围调用。

    【讨论】:

    • 谢谢。这不是为了简单和整洁而我会使用或推荐的一段代码),而是在对语言的理解上“填补一个漏洞”。
    • 关键是词法作用域;你不能不小心将赋值“注入”到你面前看不到的范围内,这与动态范围的情况不同,它是调用函数的范围 ,而不是定义的范围,这很重要。
    • 我不确定我是否理解这个问题。
    • 我可能误解了您的评论。它似乎将周围关闭范围的使用与“意外”联系起来,但在静态上下文中,它不是像示例中那样非常明确吗?
    • “相比之下,让我们假设 Python 使用了词法作用域。”我认为您的意思是“让我们假设 Python 使用了动态范围”
    猜你喜欢
    • 1970-01-01
    • 2014-11-11
    • 1970-01-01
    • 2016-11-22
    • 2018-02-11
    • 2012-04-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多