在没有自我的情况下访问类属性的困惑 - python

mit*_*tal 5 python python-2.7

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

但我有点困惑为什么以下也有效

class Crazy(object):
  VERSION = 1
  def __init__(self, version=VERSION):
    print version
Run Code Online (Sandbox Code Playgroud)

但这不

class Crazy(object):
  VERSION = 1
  def __init__(self):
    print VERSION
Run Code Online (Sandbox Code Playgroud)

dec*_*eze 7

类定义(即 内部的块)的class ...:计算方式与任何常规 Python 代码块类似。就在块的末尾class,该块内定义的每个本地名称都成为类的一部分__dict__。语法class或多或少只是语法糖:

\n
Crazy = type(\'Crazy\', (object,), {\'VERSION\': 1, ...})\n
Run Code Online (Sandbox Code Playgroud)\n

请参阅https://docs.python.org/3/library/functions.html#type

\n

考虑到这一点,您会希望它能起作用,对吗?

\n
VERSION = 1\n\ndef foo(bar=VERSION):\n    print(bar)\n
Run Code Online (Sandbox Code Playgroud)\n

(另请参阅此处以获取有关其行为的更多解释。)

\n

在块内class,它的工作方式完全相同,唯一的特殊行为是您不是创建全局名称,而是创建将成为类的名称__dict__

\n

文档中的相关段落在这里:

\n
\n

然后,使用新创建的本地命名空间和原始全局命名空间,在新的执行框架中执行 class\xe2\x80\x99s 套件(请参阅命名和绑定)。(通常,该套件主要包含函数定义。)当 class\xe2\x80\x99s 套件完成执行时,其执行帧将被丢弃,但其本地命名空间将被保存。然后使用基类的继承列表和属性字典的保存的本地命名空间创建类对象。类名绑定到原始本地命名空间中的该类对象。

\n

https://docs.python.org/3/reference/compound_stmts.html#class-definitions

\n
\n

但是,在定义类之后,该隐式名称空间不再存在,因此这不起作用:

\n
def __init__(self):\n    print(VERSION)\n
Run Code Online (Sandbox Code Playgroud)\n

范围规则遵循常规查找链:

\n
    \n
  • 它是同一函数内的局部变量吗?
  • \n
  • 它是周围函数中的非局部变量吗?
  • \n
  • 它是一个全局变量吗?
  • \n
\n

这些都不是真的,因为此刻VERSION只是 的一个属性,因此只能作为或进行访问,后者实际上也不存在,并退回到其自己的查找链上并遍历到。CrazyCrazy.VERSIONself.VERSIONCrazy.VERSION

\n