Python 中类型和对象的先有鸡还是先有蛋的悖论

Chicken or Egg paradox with type and object in Python

我记得学过 type 是它自己的实例,所有新式 classes 都继承自 object,所以我开始胡闹:

issubclass(type, object) # True
issubclass(object, type) # False
# issubclass(cls, cls) is always True
type(type) is type # True
type(object) is type # True

总而言之,type 与任何新样式 class 一样是 object 的子 class,并且与任何 class 一样, typeobject 都是 type 的实例。这是一张方便的图片:

在此声明我不是程序员,对 Python 的基本机制知之甚少,所以如果我听起来很蠢,请多多包涵。通常必须在其实例之前创建 class。然而,superclass 通常必须在它的 subclass 之前创建。将这些通用的 Python 规则应用于 typeobject 会产生明显的先有鸡还是先有蛋的悖论。

那么这些 class 中哪些是先制作的?我还怀疑因为这些 classes 是用低级语言实现的,所以它们不必遵循 Python 规则。

在Python中,一切皆对象:

  • 7 是类型 int 的对象。
  • 'foo'str 类型的对象。
  • NoneNoneType 类型的对象。
  • 如果你定义了一个classclass Foo: pass,那么Foo就是一个class类型的对象。您从 class 构造的任何对象 Foo() 都是类型 Foo 的对象。
  • 如果你将一个函数定义为def f(x): pass,,那么这个函数本身就是一个对象。

每个对象都有一个类型。但什么是类型?没错——甚至 类型本身 也是类型为 type.

的对象
issubclass(type, object) # True
issubclass(object, type) # False

根据定义,每个 class 都是 object 的子 class。 object class 不是任何东西的子class;它是所有 "objecthood" 的根源。因此 isinstance(o, object) 总是 returns True.

type(type) is type # True
type(object) is type # True

我们知道 python 中的所有内容都是 object 的实例。但是 object class 本身呢?也是一个对象。什么样的对象? object 是一种类型,就像 intstrfunction 一样。因此 object 的类型是 type。但是,object class 的任何 实例 都不是类型,而仅仅是一个对象:

type(object()) is object # True

综上所述,万物皆对象,甚至是其他对象的类型。

给non-answer一个"which comes first"的问题,其实没关系;这些东西无论如何都是抽象的,所以你可以用你想要定义的任何语义来创建一种语言,而且 "cycles".

没有错

为了给出更具体的答案,如果您对实现感兴趣,它看起来像 c-level PyObjects(变成 object)中的 typedef source code for CPython here,并与同一文件中 PyTypeObject 的 typedef 进行比较。

编辑:另一个答案更好地解释了 CPython 实现。

从语言语义的角度来看,typeobject 都存在,从程序开始的那一刻起就完全初始化了。无论实现如何使事情进入该状态,都不必遵循实现允许做的规则。

从 CPython 实现的角度来看,typeobject 都是在 C 级别静态分配的,并且都不是首先创建的。您可以在 Objects/typeobject.c 中看到变量定义。 Here's object:

PyTypeObject PyBaseObject_Type = {
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
    "object",                                   /* tp_name */
    sizeof(PyObject),                           /* tp_basicsize */
    0,                                          /* tp_itemsize */
    object_dealloc,                             /* tp_dealloc */
    0,                                          /* tp_print */
    0,                                          /* tp_getattr */
    0,                                          /* tp_setattr */
    0,                                          /* tp_reserved */
    object_repr,                                /* tp_repr */
    ...
};

here's type:

PyTypeObject PyType_Type = {
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
    "type",                                     /* tp_name */
    sizeof(PyHeapTypeObject),                   /* tp_basicsize */
    sizeof(PyMemberDef),                        /* tp_itemsize */
    (destructor)type_dealloc,                   /* tp_dealloc */
    0,                                          /* tp_print */
    0,                                          /* tp_getattr */
    0,                                          /* tp_setattr */
    0,                                          /* tp_reserved */
    (reprfunc)type_repr,                        /* tp_repr */
    ...
};

当解释器初始化开始时,typeobject都处于half-initialized状态,PyType_Ready函数负责完成它们的初始化。类型指针在变量定义中设置,但是设置超类指针是 PyType_Ready 工作的一部分,并且 PyType_Ready 需要处理大量其他初始化 - 例如,类型不还没有__dict__

顺便说一下,使用一些奇怪的元数据类 以及 Python 允许您在 user-defined 类、we can set up our own classes AB 其中 BA 的子类并且 AB 都是 B 的实例,很像 objecttype 的情况。这与 objecttype 的实际创建方式完全不同,但是:

class DummyMeta(type):
    pass

class A(type, metaclass=DummyMeta):
    pass

class B(A):
    pass

B.__class__ = B
A.__class__ = B

print(isinstance(A, B))
print(isinstance(B, B))
print(issubclass(B, A))

输出:

True
True
True