python子类访问父类的变量

gae*_*fan 34 python subclass class-variables

我很惊讶地发现子类的类变量无法访问父类的类变量而没有明确指出父类的类名:

>>> class A(object):
...     x = 0
... 
>>> class B(A):
...     y = x+1
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in B
NameError: name 'x' is not defined
>>> class B(A):
...     y = A.x + 1
... 
>>> B.x
0
>>> B.y
1
Run Code Online (Sandbox Code Playgroud)

为什么在定义中我必须引用Ax而不仅仅是x?这与我对实例变量的直觉相反,因为我可以在定义B之后引用Bx.

Ale*_*lli 49

Python的裸名称范围规则非常简单明了:首先是本地名称空间,然后是(如果有的话)当前嵌套的外部函数,然后是全局变量,最后是内置函数.这就是查找裸名时所发生的一切,并且不需要记忆或应用任何复杂的规则(也不需要Python编译器来执行更复杂的规则).

每当您想要不同的查找时,您将使用限定名称,而不是名称.限定名称的功能要强大得多,因为查找总是可以委托给可以请求其属性的对象,并且这些对象可以实现他们需要的任何查找规则.特别是,在一个类中的实例方法,self.x问路self对象查找属性名称'x'-并且在查找它可以委托给类,包括继承的概念(和多重继承,法决议的执行情况订单等等).

类的主体(与类中定义的方法的主体相对)作为class语句的一部分执行,创建类对象或绑定其名称之前(特别是在任何基础被定义为之前)作为基础 - 尽管这个最新的细节无论如何都指的是无论如何! - ).

因此,在您的示例中,在类中B,x使用通用规则查找裸名称 - 是否是本地绑定的名称?如果不是,它是否绑定在嵌套此范围的任何外部函数中?如果不是,它是绑定为全局还是内置?如果不是上述情况,使用当前的裸名称会导致名称错误异常.

由于您希望查找序列不同于普遍强制执行的裸名查找规则,因此显然您需要使用限定名称,而不是名字; 片刻的反思将清楚地表明,"一个显而易见的选择"为用你的目的有资格的名称必须A.x-因为这就是你它要查找(基地没有任何地方记录在那毕竟......通常type,在类主体执行完毕后调用base-binding作为其工作的一部分时,它将成为元类! - ).

有些人如此敏锐地依赖其他"魔法"规则查找裸名,他们无法忍受Python的这一方面(我相信,最初是受到Modula-3的启发,这是一种在理论上得到很好考虑的鲜为人知的语言'circles ;-) - 必须写self.x一个方法来指定x必须查找self而不是使用通用的barename规则,例如,驱动这样的人.

我,我喜欢裸名查找规则的简单性和普遍性,我喜欢在任何时候想要任何其他形式的查找时使用合格的名称而不是姓名...但是,这并不是我疯狂爱上的秘密Python的(我有自己的怨言-例如,global x作为一个语句总是让我的皮肤爬行,在那里我宁愿写global.x的,即具有global可内置名为"当前正在执行的模块" ......我的爱合格的名字! - ),是吗? - )

  • 但是如果你的子类有一系列超类怎么办?然后,限定名称要求您知道设置类变量的超类.当然,我可以看到这种要求使事情变得更安全的情况,但也有一些情况是限制的.似乎对类变量有一个等价的'super'会很好. (5认同)

Nat*_*vis 26

在Python中,类的主体在创建类之前在其自己的命名空间中执行(之后,该命名空间的成员将成为类的成员).因此,当解释器达到y = x + 1时,B类在那时尚不存在,因此没有父级.

有关更多详细信息,请参阅http://docs.python.org/reference/compound_stmts.html#class-definitions