首页 > 解决方案 > 对象在动态类型创建期间被子类化,但不是在 python2 中的经典类定义期间

问题描述

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

class X:
    a = 1

而且,在 Python 3 中,由于新样式 classesX自动继承自object,但在 Python 2 中,它不会:

>>> X.__bases__ # Python 2
()
>>> X.__bases__ # Python 3
(<class 'object'>,)

而且我们还知道我们可以使用类型工厂动态创建这样一个类:

X = type("X",(object,), {"a":1})
      name^   ^bases     ^ "class" body

但是,如果我们像使用语法一样省略object元组中的classobject

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

我希望X.__bases__在 python 2 中是空的。
而且它不是这样一个记录的功能,我在互联网上几乎找不到关于这个的东西。

事实上,python 的官方文档自相矛盾地指出:

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

但是,如上所示,在 Python 2 中()仍然会导致,所以它成为属性(<type 'object'>,)并不是真的。__bases__

谁能解释这种行为?

标签: pythonpython-3.xpython-2.7class

解决方案


让我们看看这个 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)

types.ClassType被描述为:

用户定义的旧式类的类型。

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

>>> X3 = types.ClassType('X3', (), {'a': 1})
>>> X3.__bases__
2: () 

作为参考,摘自 Python 2 的New-style and classic classes

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

直到 Python 2.1 的概念class与 的概念无关 type,旧式类是唯一可用的风格。对于旧式类,该语句x.__class__提供x类,但 type(x)始终是<type 'instance'>。这反映了一个事实,即所有旧式实例,独立于它们的类,都是用一个称为instance.

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


推荐阅读