我知道我们可以使用self
或class
名称访问类属性。
但是我很困惑为什么以下内容也有效
class Crazy(object):
VERSION = 1
def __init__(self, version=VERSION):
print version
但这不是
class Crazy(object):
VERSION = 1
def __init__(self):
print VERSION
类定义,即class ...:
中的块,就像任何常规的python代码块一样评估。就在class
块的末尾,该块内定义的每个本地名称都成为类'__dict__
的一部分。class
语法或多或少只是句法糖:
Crazy = type('Crazy', (object,), {'VERSION': 1, ...})
请参阅https://docs.python.org/3/library/functions.html#type。
给出了这个,您希望这能起作用,对吧?
VERSION = 1
def foo(bar=VERSION):
print(bar)
(有关其行为的更多解释,也请参见此信息。(
在class
块内部,这种方式完全相同,而您唯一的特殊行为是您未创建 global 名称,而是将成为类'__dict__
的名称。
文档中的相关段落在这里:
然后使用新创建的本地名称空间和原始的全局名称空间在新的执行框架(请参阅命名和绑定(中执行该类套件。(通常,套件主要包含功能定义。(当类的套件完成执行时,其执行框架被丢弃,但保存其本地名称空间。然后使用基本类的继承列表以及属性词典保存的本地名称空间创建类对象。类名称在原始本地名称空间中绑定到此类对象。
https://docs.python.org/3/reference/compound_stmts.html#class-definitions
定义了类后,该隐式名称空间不再存在,因此这不起作用:
def __init__(self):
print(VERSION)
范围规则遵循常规查找链:
- 它是同一函数内部的局部变量吗?
- 它是周围函数中的非局部变量吗?
- 它是全局变量吗?
这些都不是真实的,因为VERSION
在这一点上只是Crazy
的属性,因此只能作为Crazy.VERSION
或self.VERSION
访问,后者实际上也不存在,并落在其自己的查找链上,并遍历遍历到Crazy.VERSION
。