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

时间:2019-07-03 11:19:50

标签: python-2.7

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

但是我有些困惑,为什么下面的方法同样有用

class Crazy(object):
  VERSION = 1
  def __init__(self, version=VERSION):
    print version

但这不是

class Crazy(object):
  VERSION = 1
  def __init__(self):
    print VERSION

1 个答案:

答案 0 :(得分:3)

一个类定义,即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)

(有关其行为的更多解释,请参见this。)

class块中,此方法的工作方式完全相同,唯一的特殊行为是您不会创建 global 名称,但会创建类的名称{{1 }}。

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

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

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

尽管在定义了类之后,该隐式命名空间不再存在,所以它不起作用:

__dict__

作用域规则遵循常规查找链:

  • 是同一函数中的局部变量吗?
  • 在周围的函数中它是非局部变量吗?
  • 是全局变量吗?

这些都不是正确的,因为此时def __init__(self): print(VERSION) 只是VERSION的一个属性,因此只能以CrazyCrazy.VERSION的形式访问,后者实际上实际上也不存在,而是退回到它自己的查找链上并遍历到self.VERSION

相关问题