访问班级属性而无需自我python时的混乱



我知道我们可以使用selfclass名称访问类属性。

但是我很困惑为什么以下内容也有效

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.VERSIONself.VERSION访问,后者实际上也不存在,并落在其自己的查找链上,并遍历遍历到Crazy.VERSION

最新更新