类定义中的变量范围令人困惑

Posted

技术标签:

【中文标题】类定义中的变量范围令人困惑【英文标题】:Variable scopes inside class definitions are confusing 【发布时间】:2019-05-23 05:09:30 【问题描述】:

由于某些原因,当出现这种情况时,python 从全局命名空间获取变量:

class Cls:
    foo = foo

请看这段代码:

foo = 'global'

def func0():
    foo = 'local'
    class Cls:
        bar = foo
    print('func0', Cls.bar)
 func0()
 # func0 local

def func1():
    foo = 'local'
    class Cls:
        foo = foo
    print('func1', Cls.foo)
func1()
# func1 global

def func2():
    foo = 'nonlocal'
    def internal():
        class Cls:
            foo = foo
        print('func2.internal', Cls.foo)
    internal()
func2()
# func2.internal global

def func3():
    foo = 'local'
    class Cls:
        bar = foo
        foo = foo
    print('func3', Cls.bar, Cls.foo)
func3()
# func3 global global

按照PEP 227

类定义是一个可执行语句,可能包含名称的使用和定义。这些引用遵循名称解析的正常规则。类定义的命名空间成为类的属性字典。

但在我看来,这根本不像是“遵循正常规则”。我错过了什么?

Py2 和 Py3 都是这样操作的。

【问题讨论】:

@DeepSpace 我期待赋值右侧的评估应该独立于左侧的变量名,但这里不是这种情况。当您在类定义中执行 a = b 时,它会从本地命名空间获得 b,但随后 a = a 它会从全局命名空间获得正确的 a a 还能从哪里获得? 来自本地命名空间,请查看func0 在我看来,它应该像在函数的命名空间中一样引发UnboundLocalError,但由于某些原因它不会 【参考方案1】:

Execution model - Resolution of names:

中记录了这一点

类定义块 [...] 是特殊的 在名称解析的上下文中。类定义是可执行文件 可以使用和定义名称的语句。这些参考遵循 名称解析的正常规则,unbound local 除外 在全局命名空间中查找变量。

(强调我的)

【讨论】:

谢谢,这就是我要找的!也许您可以提供任何有关这种行为动机的见解?

以上是关于类定义中的变量范围令人困惑的主要内容,如果未能解决你的问题,请参考以下文章

关于 CoffeeScript 变量范围的困惑

Excel,查看表中的值,其中行和列都是范围

异步nodejs中的每个变量范围

指令的angularjs typescript控制器类中未定义的范围变量

PHP 范围解析操作符 (::)

在同一类中的 setTimeout 期间维护变量