为什么__base__在类正文中不可访问?

时间:2019-05-27 07:31:05

标签: python class inheritance

Class对象具有__bases__(和__base__)属性:

>>> class Foo(object):
...     pass
... 
>>> Foo.__bases__
(<class 'object'>,)

遗憾的是,这些属性无法在类主体中访问,这对于访问父类属性非常方便,而无需硬编码名称:

class Foo:
    cls_attr = 3

class Bar(Foo):
    cls_attr = __base__.cls_attr + 2
    # throws NameError: name '__base__' is not defined

在类正文中无法访问__bases____base__的原因吗?

(要清楚,我要问的是这是一个有意识的设计决策。我不是在问实现;我知道__bases__type中的一个描述符,并且这个描述符在创建类对象之前无法访问。我想知道为什么python不会在类主体中将__bases__创建为局部变量。)

3 个答案:

答案 0 :(得分:6)

  

我想知道为什么python不在类主体中创建__bases__作为局部变量

如您所知,class主要是type.__new__()的快捷方式-当运行时命中class语句时,它将在{{1}的顶层执行所有语句}主体,在专用命名空间dict中收集所有结果绑定,使用具体的元类,类名,基类和命名空间dict调用class,并将结果类对象绑定到封闭范围内的类名(通常但不一定是模块的顶级名称空间)。

这里的重点是,建立类对象并允许自定义类对象的创建是元类的责任,元类必须可以自由地对其参数进行任何操作。通常,自定义元类将主要用于type()字典,但是它也必须能够与attrs参数混淆。现在,由于仅在执行类主体语句之后才调用元类,因此运行时无法可靠地在类主体范围中公开bases,因为这些基数可以在以后由元类修改。

这里还有更多的哲学方面的考虑,特别是wrt / explicit和隐式,并且如shx2所提到的,Python设计人员试图避免魔术变量突然出现。确实有几个实现变量(bases,在py3中,__module__)是在类主体名称空间中“自动”定义的,但它们只是名称,主要用作其他调试/检查信息对于开发人员而言),并且绝对不会对类对象的创建或其属性,行为和其他方面产生任何影响。

与Python一样,您必须考虑整个上下文(执行模型,对象模型,不同部分如何协同工作等),才能真正理解设计选择。您是否同意整个设计和哲学是另一个争论(并且不属于这里),但是您可以肯定的是,这些选择 是“有意识的设计决策”。

答案 1 :(得分:2)

我没有回答为什么决定按原样实现,而是回答为什么没有将其实现为“类体中的局部变量”:

仅仅因为python中没有任何东西是在类体中神奇定义的局部变量。 Python不喜欢魔术般地出现的名字。

答案 2 :(得分:0)

这是因为它尚未创建。

请考虑以下内容:

type

假想打印结果如何? 每个python类都是通过int元类以某种方式创建的。 您在type()参数中拥有bases的{​​{1}}参数,但是您不知道返回值是多少。您可以将其直接用作元类的基础,也可以随LOC返回另一个基础。

刚刚意识到您的to be clear部分,现在我的回答是无用的哈哈。哦,好了