带有Python中类型和对象的鸡肉或鸡蛋悖论

时间:2019-06-08 00:53:04

标签: python object types instance subclass

我记得曾经得知type是它自己的实例,并且所有新式类都继承自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就像任何新型类都是object的子类,而typeobject都是实例type中的。这是一个方便的图片:

Picture of relationship between type and object in Python

这里有一个很大的免责声明,我不是程序员,并且对Python的基本机制知之甚少,所以如果我听起来很笨,请多多包涵。通常,必须在其实例之前创建一个类。但是,通常必须在其子类之前创建超类。将这些通用Python规则应用于typeobject会产生明显的鸡蛋悖论。

那么这些类中的哪一个首先被制成?我还怀疑,因为这些类是用较低级的语言实现的,所以它们不必遵循Python规则。

2 个答案:

答案 0 :(得分:2)

从语言语义学的角度来看,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都处于半初始化状态,而PyType_Ready函数负责完成其初始化。类型指针是在变量定义中设置的,但是设置超类指针是PyType_Ready的工作之一,PyType_Ready需要处理许多其他初始化-例如,类型还没有__dict__

偶然地,使用一些奇怪的元类,并且Python允许您在用户定义的类we can set up our own classes __class__A的实例上重新分配B,其中{{ 1}}是B的子类,而AA都是B的实例,非常类似于Bobject的情况。不过,这与实际创建typeobject的方式不同:

type

输出:

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))

答案 1 :(得分:1)

在Python中,一切都是对象:

  • 7是类型int的对象。
  • 'foo'是类型str的对象。
  • None是类型NoneType的对象。
  • 如果定义类class Foo: pass,则Foo是类型class的对象。从该类构造的任何对象Foo()都是类型Foo的对象。
  • 如果将函数定义为def f(x): pass,,则该函数本身就是对象。

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

issubclass(type, object) # True
issubclass(object, type) # False

根据定义,每个类都是object的子类。 object类不是任何东西的子类。这是所有“客观性”的根源。因此,isinstance(o, object)总是返回True

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

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

type(object()) is object # True

总而言之,一切都是对象,甚至是其他对象的类型。

要回答“先到先得”这个问题,这并不重要;这些东西无论如何都是抽象的,因此您可以使用自己想定义的任何语义来制作语言,而“循环”没有任何问题。

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

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