对象在动态类型创建期间被子类化,但在python2中的经典类定义期间不被子类化

Ade*_*lin 8 python class python-2.7 python-3.x

我们知道这会创建一个类:

class X:
    a = 1
Run Code Online (Sandbox Code Playgroud)

并且,在Python 3中,由于使用了新的样式类,因此会X自动从继承object,但是在Python 2中,它不会:

>>> X.__bases__ # Python 2
()
>>> X.__bases__ # Python 3
(<class 'object'>,)
Run Code Online (Sandbox Code Playgroud)

我们也知道,我们可以使用类工厂动态创建这样的一个类:

X = type("X",(object,), {"a":1})
      name^   ^bases     ^ "class" body
Run Code Online (Sandbox Code Playgroud)

然而,如果我们忽略了object基地的元组就像我们用做class语法,我们继承object的python3和,出乎意料的是,在python2还有:

X = type("X", ( ), {"a":1})
               ^ empty bases tuple
Run Code Online (Sandbox Code Playgroud)
>>> X.__bases__ # Python 2
(<type 'object'>,)
>>> X.__bases__ # Python 3
(<class 'object'>,)
Run Code Online (Sandbox Code Playgroud)

我期望X.__bases__在python 2中是空的。
而且它不是这样的文档化功能,我几乎无法在Internet上找到有关此功能的信息。

实际上,python的官方文档矛盾地指出:

基元组逐项列出基类并成为__bases__属性

但是,如上所示,它()仍然会(<type 'object'>,)在Python 2中生成,因此将它变成__bases__属性并不是真的。

谁能解释这种行为?

saa*_*aaj 5

让我们看看这个Python 2 shell。

>>> class X1:
...     a = 1
... 
... X2 = type('X2', (), {'a': 1})
>>> type(X1)
0: <type 'classobj'>
>>> type(X2)
1: <type 'type'>
>>> import types
>>> assert types.ClassType is type(X1)
Run Code Online (Sandbox Code Playgroud)

types.ClassType 被描述为:

用户定义的旧类的类型。

基本上type在新样式类的默认元类中。如果要使用旧样式的元编程,则可以types.ClassType以相同的方式使用。

>>> X3 = types.ClassType('X3', (), {'a': 1})
>>> X3.__bases__
2: () 
Run Code Online (Sandbox Code Playgroud)

作为参考,摘录自Python 2的New-class和classic类

类和实例有两种风格:旧样式(或经典样式)和新样式。

在Python 2.1之前,的概念class与的概念无关 type,而旧式类是唯一可用的样式。对于老式类,该语句x.__class__提供x的类,但 type(x)始终为<type 'instance'>。这反映了一个事实,即所有旧式实例(独立于其类)均使用称为的单个内置类型实现instance

新样式类在Python 2.2引入了统一的概念 classtype。新型类只是用户定义的类型,不多也不少。如果x是新样式类的实例,则type(x) 通常与x相同x.__class__(尽管不能保证-允许新样式类实例覆盖为返回的值 x.__class__)。