# 类型对象结构体

Python 对象系统中最重要的一个结构体也许是定义新类型的结构体: `PyTypeObject` 结构体。 类型对象可以使用任何 `PyObject_*` 或 `PyType_*` 函数来处理，但并未提供大多数 Python 应用程序会感兴趣的东西。 这些对象是对象行为的基础，所以它们对解释器本身及任何实现新类型的扩展模块都非常重要。

与大多数标准类型相比，类型对象相当大。这么大的原因是每个类型对象存储了大量的值，大部分是C函数指针，每个指针实现了类型功能的一小部分。本节将详细描述类型对象的字段。这些字段将按照它们在结构中出现的顺序进行描述。

除了下面的快速参考， 例子 小节提供了快速了解 `PyTypeObject` 的含义和用法的例子。

## 快速参考

### "tp 槽位"

PyTypeObject 槽位 [1] | 类型 | 特殊方法/属性 | 信息 [2]
--- | --- | --- | ---
O | T | D | I
<R> `tp_name` | const char * | __name__ | X | X |  |
`tp_basicsize` | `Py_ssize_t` |  | X | X |  | X
`tp_itemsize` | `Py_ssize_t` |  |  | X |  | X
`tp_dealloc` | `destructor` |  | X | X |  | X
`tp_vectorcall_offset` | `Py_ssize_t` |  |  | X |  | X
(`tp_getattr`) | `getattrfunc` | __getattribute__, __getattr__ |  |  |  | G
(`tp_setattr`) | `setattrfunc` | __setattr__, __delattr__ |  |  |  | G
`tp_as_async` | `PyAsyncMethods` * | 子槽位 |  |  |  | %
`tp_repr` | `reprfunc` | __repr__ | X | X |  | X
`tp_as_number` | `PyNumberMethods` * | 子槽位 |  |  |  | %
`tp_as_sequence` | `PySequenceMethods` * | 子槽位 |  |  |  | %
`tp_as_mapping` | `PyMappingMethods` * | 子槽位 |  |  |  | %
`tp_hash` | `hashfunc` | __hash__ | X |  |  | G
`tp_call` | `ternaryfunc` | __call__ |  | X |  | X
`tp_str` | `reprfunc` | __str__ | X |  |  | X
`tp_getattro` | `getattrofunc` | __getattribute__, __getattr__ | X | X |  | G
`tp_setattro` | `setattrofunc` | __setattr__, __delattr__ | X | X |  | G
`tp_as_buffer` | `PyBufferProcs` * | 子槽位 |  |  |  | %
`tp_flags` | unsigned long |  | X | X |  | ?
`tp_doc` | const char * | __doc__ | X | X |  |
`tp_traverse` | `traverseproc` |  |  | X |  | G
`tp_clear` | `inquiry` |  |  | X |  | G
`tp_richcompare` | `richcmpfunc` | __lt__, __le__, __eq__, __ne__, __gt__, __ge__ | X |  |  | G
(`tp_weaklistoffset`) | `Py_ssize_t` |  |  | X |  | ?
`tp_iter` | `getiterfunc` | __iter__ |  |  |  | X
`tp_iternext` | `iternextfunc` | __next__ |  |  |  | X
`tp_methods` | `PyMethodDef` [] |  | X | X |  |
`tp_members` | `PyMemberDef` [] |  |  | X |  |
`tp_getset` | `PyGetSetDef` [] |  | X | X |  |
`tp_base` | `PyTypeObject` * | __base__ |  |  | X |
`tp_dict` | `PyObject` * | __dict__ |  |  | ? |
`tp_descr_get` | `descrgetfunc` | __get__ |  |  |  | X
`tp_descr_set` | `descrsetfunc` | __set__, __delete__ |  |  |  | X
(`tp_dictoffset`) | `Py_ssize_t` |  |  | X |  | ?
`tp_init` | `initproc` | __init__ | X | X |  | X
`tp_alloc` | `allocfunc` |  | X |  | ? | ?
`tp_new` | `newfunc` | __new__ | X | X | ? | ?
`tp_free` | `freefunc` |  | X | X | ? | ?
`tp_is_gc` | `inquiry` |  |  | X |  | X
<`tp_bases`> | `PyObject` * | __bases__ |  |  | ~ |
<`tp_mro`> | `PyObject` * | __mro__ |  |  | ~ |
[`tp_cache`] | `PyObject` * |  |  |  |
[`tp_subclasses`] | void * | __subclasses__ |  |  |
[`tp_weaklist`] | `PyObject` * |  |  |  |
(`tp_del`) | `destructor` |  |  |  |  |
[`tp_version_tag`] | unsigned int |  |  |  |
`tp_finalize` | `destructor` | __del__ |  |  |  | X
`tp_vectorcall` | `vectorcallfunc` |  |  |  |  |
[`tp_watched`] | unsigned char |  |  |  |  |

[ 1 ]

（）：括号中的插槽名称表示（实际上）已弃用。

<>: 尖括号内的名称在初始时应设为 `NULL` 并被视为是只读的。

[]: 方括号内的名称仅供内部使用。

<R> (作为前缀) 表示字段是必需的 (不能是 `NULL`)。

[ 2 ]

列：

"O": 在 `PyBaseObject_Type` 上设置

"T": 在 `PyType_Type` 上设置

"D": 默认设置(如果方法槽被设置为NULL)

    X - PyType_Ready 如其为 NULL 则设置该值
    ~ - PyType_Ready 始终设置该值 (它应当为 NULL)
    ? - PyType_Ready 根据其他槽位可能设置该值

    另请参阅继承列 ("I")。

"I": 继承

    X - 如果使用 *NULL* 值定义则类型槽位将通过 *PyType_Ready* 继承
    % - 子结构体的槽位是单独继承的
    G - 已继承，但仅会与其他槽位相结合；参见槽位的说明
    ? - 较复杂；参见槽位的说明

注意，有些方法槽是通过普通属性查找链有效继承的。

### 子槽位

槽位 | 类型 | 特殊方法
--- | --- | ---
`am_await` | `unaryfunc` | __await__
`am_aiter` | `unaryfunc` | __aiter__
`am_anext` | `unaryfunc` | __anext__
`am_send` | `sendfunc` |
`nb_add` | `binaryfunc` | __add__ __radd__
`nb_inplace_add` | `binaryfunc` | __iadd__
`nb_subtract` | `binaryfunc` | __sub__ __rsub__
`nb_inplace_subtract` | `binaryfunc` | __isub__
`nb_multiply` | `binaryfunc` | __mul__ __rmul__
`nb_inplace_multiply` | `binaryfunc` | __imul__
`nb_remainder` | `binaryfunc` | __mod__ __rmod__
`nb_inplace_remainder` | `binaryfunc` | __imod__
`nb_divmod` | `binaryfunc` | __divmod__ __rdivmod__
`nb_power` | `ternaryfunc` | __pow__ __rpow__
`nb_inplace_power` | `ternaryfunc` | __ipow__
`nb_negative` | `unaryfunc` | __neg__
`nb_positive` | `unaryfunc` | __pos__
`nb_absolute` | `unaryfunc` | __abs__
`nb_bool` | `inquiry` | __bool__
`nb_invert` | `unaryfunc` | __invert__
`nb_lshift` | `binaryfunc` | __lshift__ __rlshift__
`nb_inplace_lshift` | `binaryfunc` | __ilshift__
`nb_rshift` | `binaryfunc` | __rshift__ __rrshift__
`nb_inplace_rshift` | `binaryfunc` | __irshift__
`nb_and` | `binaryfunc` | __and__ __rand__
`nb_inplace_and` | `binaryfunc` | __iand__
`nb_xor` | `binaryfunc` | __xor__ __rxor__
`nb_inplace_xor` | `binaryfunc` | __ixor__
`nb_or` | `binaryfunc` | __or__ __ror__
`nb_inplace_or` | `binaryfunc` | __ior__
`nb_int` | `unaryfunc` | __int__
`nb_reserved` | void * |
`nb_float` | `unaryfunc` | __float__
`nb_floor_divide` | `binaryfunc` | __floordiv__
`nb_inplace_floor_divide` | `binaryfunc` | __ifloordiv__
`nb_true_divide` | `binaryfunc` | __truediv__
`nb_inplace_true_divide` | `binaryfunc` | __itruediv__
`nb_index` | `unaryfunc` | __index__
`nb_matrix_multiply` | `binaryfunc` | __matmul__ __rmatmul__
`nb_inplace_matrix_multiply` | `binaryfunc` | __imatmul__
`mp_length` | `lenfunc` | __len__
`mp_subscript` | `binaryfunc` | __getitem__
`mp_ass_subscript` | `objobjargproc` | __setitem__, __delitem__
`sq_length` | `lenfunc` | __len__
`sq_concat` | `binaryfunc` | __add__
`sq_repeat` | `ssizeargfunc` | __mul__
`sq_item` | `ssizeargfunc` | __getitem__
`sq_ass_item` | `ssizeobjargproc` | __setitem__ __delitem__
`sq_contains` | `objobjproc` | __contains__
`sq_inplace_concat` | `binaryfunc` | __iadd__
`sq_inplace_repeat` | `ssizeargfunc` | __imul__
`bf_getbuffer` | `getbufferproc()` | __buffer__
`bf_releasebuffer` | `releasebufferproc()` | __release_buffer__

### 槽位 typedef

typedef | 参数类型 | 返回类型
--- | --- | ---
`allocfunc` | `PyTypeObject` * `Py_ssize_t` | `PyObject` *
`destructor` | `PyObject` * | void
`freefunc` | void * | void
`traverseproc` | `PyObject` * `visitproc` void * | int
`newfunc` | `PyTypeObject` * `PyObject` * `PyObject` * | `PyObject` *
`initproc` | `PyObject` * `PyObject` * `PyObject` * | int
`reprfunc` | `PyObject` * | `PyObject` *
`getattrfunc` | `PyObject` * const char * | `PyObject` *
`setattrfunc` | `PyObject` * const char * `PyObject` * | int
`getattrofunc` | `PyObject` * `PyObject` * | `PyObject` *
`setattrofunc` | `PyObject` * `PyObject` * `PyObject` * | int
`descrgetfunc` | `PyObject` * `PyObject` * `PyObject` * | `PyObject` *
`descrsetfunc` | `PyObject` * `PyObject` * `PyObject` * | int
`hashfunc` | `PyObject` * | Py_hash_t
`richcmpfunc` | `PyObject` * `PyObject` * int | `PyObject` *
`getiterfunc` | `PyObject` * | `PyObject` *
`iternextfunc` | `PyObject` * | `PyObject` *
`lenfunc` | `PyObject` * | `Py_ssize_t`
`getbufferproc` | `PyObject` * `Py_buffer` * int | int
`releasebufferproc` | `PyObject` * `Py_buffer` * | void
`inquiry` | `PyObject` * | int
`unaryfunc` | `PyObject` * | `PyObject` *
`binaryfunc` | `PyObject` * `PyObject` * | `PyObject` *
`ternaryfunc` | `PyObject` * `PyObject` * `PyObject` * | `PyObject` *
`ssizeargfunc` | `PyObject` * `Py_ssize_t` | `PyObject` *
`ssizeobjargproc` | `PyObject` * `Py_ssize_t` `PyObject` * | int
`objobjproc` | `PyObject` * `PyObject` * | int
`objobjargproc` | `PyObject` * `PyObject` * `PyObject` * | int

请参阅 槽位类型 typedef 里有更多详细信息。

## PyTypeObject 定义

针对 `PyTypeObject` 的结构定义可以在 `Include/cpython/object.h` 中找到。 为了方便参考，这里复述了其中的定义：

    typedef struct _typeobject {
        PyObject_VAR_HEAD
        const char *tp_name; /* 用于打印，格式为 "<module>.<name>" */
        Py_ssize_t tp_basicsize, tp_itemsize; /* 用于分配 */

        /* 用于实现标准操作的方法 */

        destructor tp_dealloc;
        Py_ssize_t tp_vectorcall_offset;
        getattrfunc tp_getattr;
        setattrfunc tp_setattr;
        PyAsyncMethods *tp_as_async; /* 原名为 tp_compare (Python 2)
                                        或 tp_reserved (Python 3) */
        reprfunc tp_repr;

        /* 用于标准类的方法集 */

        PyNumberMethods *tp_as_number;
        PySequenceMethods *tp_as_sequence;
        PyMappingMethods *tp_as_mapping;

        /* 更多标准操作 (这些用于二进制兼容) */

        hashfunc tp_hash;
        ternaryfunc tp_call;
        reprfunc tp_str;
        getattrofunc tp_getattro;
        setattrofunc tp_setattro;

        /* 用于以输入/输出缓冲区方式访问对象的函数 */
        PyBufferProcs *tp_as_buffer;

        /* 用于定义可选/扩展特性是否存在的旗标 */
        unsigned long tp_flags;

        const char *tp_doc; /* 文档字符串 */

        /* 在 2.0 发布版中分配的含义 */
        /* 为所有可访问的对象调用函数 */
        traverseproc tp_traverse;

        /* 删除对所包含对象的引用 */
        inquiry tp_clear;

        /* 在 2.1 发布版中分配的含义 */
        /* 富比较操作 */
        richcmpfunc tp_richcompare;

        /* 启用弱引用 */
        Py_ssize_t tp_weaklistoffset;

        /* 迭代器 */
        getiterfunc tp_iter;
        iternextfunc tp_iternext;

        /* 属性描述器和子类化内容 */
        PyMethodDef *tp_methods;
        PyMemberDef *tp_members;
        PyGetSetDef *tp_getset;
        // 堆类型的强引用，静态类型的借入引用
        PyTypeObject *tp_base;
        PyObject *tp_dict;
        descrgetfunc tp_descr_get;
        descrsetfunc tp_descr_set;
        Py_ssize_t tp_dictoffset;
        initproc tp_init;
        allocfunc tp_alloc;
        newfunc tp_new;
        freefunc tp_free; /* 层级的释放内存例程 */
        inquiry tp_is_gc; /* 用于 PyObject_IS_GC */
        PyObject *tp_bases;
        PyObject *tp_mro; /* 方法解析顺序 */
        PyObject *tp_cache; /* 不再被使用 */
        void *tp_subclasses;  /* 对于静态内置类型这将是一个索引 */
        PyObject *tp_weaklist; /* 不被用于静态内置类型 */
        destructor tp_del;

        /* 类型属性缓存版本标签。 在 2.6 版中添加。
         * 如果为零，则缓存无效并且必须被初始化。
         */
        unsigned int tp_version_tag;

        destructor tp_finalize;
        vectorcallfunc tp_vectorcall;

        /* 类型监视器针对此类型的位设置 */
        unsigned char tp_watched;

        /* 使用的 tp_version_tag 值数量。
         * 如果针对此类型的属性缓存被禁用则设为 _Py_ATTR_CACHE_UNUSED
         * （例如由于自定义的 MRO 条目而被禁用）。
         * 在其他情况下，将被限制为 MAX_VERSIONS_PER_CLASS (在其他地方定义)。
         */
        uint16_t tp_versions_used;
    } PyTypeObject;

## PyObject 槽位

类型对象结构体扩展了 `PyVarObject` 结构体。 `ob_size` 字段用于动态类型（由 `type_new()` 创建，通常由 class 语句调用）。 请注意 `PyType_Type` （元类型）会初始化 `tp_itemsize`，这意味着它的实例（即类型对象） 必须 具有 `ob_size` 字段。

`PyObject.ob_refcnt`

> 类型对象的引用计数由 `PyObject_HEAD_INIT` 宏初始化为 `1`。请注意，对于 静态分配的类型对象，该类型的实例（其 `ob_type` 指回类型的对象）*不* 计为引用。但对于 动态分配的类型对象，实例 确实 计为引用。

> 继承：

> 子类型不继承此字段。

`PyObject.ob_type`

> 这是类型的类型，换句话说就是元类型，它由宏 `PyObject_HEAD_INIT` 的参数来做初始化，它的值一般情况下是 `&PyType_Type` 。可是为了使动态可载入扩展模块至少在Windows上可用，编译器会报错这是一个不可用的初始化。因此按照惯例传递 `NULL` 给宏 `PyObject_HEAD_INIT` 并且在模块的初始化函数开始时候其他任何操作之前初始化这个字段。典型做法是这样的：

>     Foo_Type.ob_type = &PyType_Type;

> 这应当在创建类型的任何实例之前完成。 `PyType_Ready()` 会检查 `ob_type` 是否为 `NULL`，如果是，则将其初始化为基类的 `ob_type` 字段。 如果该字段为非零值则 `PyType_Ready()` 将不会更改它。

> 继承：

> 此字段会被子类型继承。

## PyVarObject 槽位

`PyVarObject.ob_size`

> 对于 静态分配的内存对象，它应该初始化为 0。对于 动态分配的类型对象，该字段具有特殊的内部含义。

> 应使用 `Py_SIZE()` 宏来访问此字段。

> 继承：

> 子类型不继承此字段。

## PyTypeObject 槽

每个槽位都有一个小节来描述继承关系。 如果 `PyType_Ready()` 可以在字段被设为 `NULL` 时设置一个值那么还会有一个“默认”小节。 （请注意在 `PyBaseObject_Type` 和 `PyType_Type` 上设置的许多字段实际上就是默认值。）

const char * PyTypeObject .tp_name

  指向包含类型名称的以 NUL 结尾的字符串的指针。 对于可作为模块全局访问的类型，该字符串应为模块全名，后面跟一个点号，然后再加类型名称；对于内置类型，它应当只是类型名称。 如果模块是包的子模块，则包的全名将是模块的全名的一部分。 例如，在包 `P` 的子包 `Q` 中的模块 `M` 中定义的名为 `T` 的类型应当具有 `tp_name` 初始化器 `"P.Q.M.T"`。

  对于 动态分配的类型对象，这应为类型名称，而模块名称将作为 `'__module__'` 键的值显式地保存在类型字典中。

  对于 静态分配的类型对象，tp_name 字段应当包含一个点号。 最后一个点号之前的所有内容都可作为 `__module__` 属性访问，而最后一个点号之后的所有内容都可作为 `__name__` 属性访问。

  如果不存在点号，则整个 `tp_name` 字段将作为 `__name__` 属性访问，而 `__module__` 属性则将是未定义的（除非在字典中显式地设置，如上文所述）。 这意味着无法对你的类型执行 pickle。 此外，它也不会在用 pydoc 创建的模块文档中列出。

  该字段不可为 `NULL`。 它是 `PyTypeObject()` 中唯一的必填字段（除了潜在的 `tp_itemsize` 以外）。

  继承：

  子类型不继承此字段。

Py_ssize_t PyTypeObject .tp_basicsize
Py_ssize_t PyTypeObject .tp_itemsize

  通过这些字段可以计算出该类型实例以字节为单位的大小。

  类型可分为两种：实例为固定长度且 `tp_itemsize` 字段值为零的类型；实例为可变长度且 `tp_itemsize` 字段值不为零的类型。 对于实例为固定长度的类型，所有实例都具有相同的由 `tp_basicsize` 给出的大小。 （这条规则的例外情况可通过使用 `PyUnstable_Object_GC_NewWithExtraData()` 来实现。）

  对于实例为可变长度的类型，其实例必须具有 `ob_size` 字段，且实例大小为 `tp_basicsize` 加 N 乘以 `tp_itemsize`，其中 N 为对象的“长度”。

  像 `PyObject_NewVar()` 这样的函数接受 N 值作为参数，并会将其保存在实例的 `ob_size` 字段中。 请注意 `ob_size` 字段在此之后可能还有其他用处。 例如，`int` 实例会以具体实现所定义的方式来使用 `ob_size` 的比特位；下层的存储及其大小应当使用 `PyLong_Export()` 来访问。

  备注

  `ob_size` 字段应当使用 `Py_SIZE()` 和 `Py_SET_SIZE()` 宏来访问。

  此外，实例布局中存在 `ob_size` 字段并不意味着该实例结构体是可变长度的。 例如，`list` 类型实例即为固定长度，虽然其实例具有 `ob_size` 字段。 （和 `int` 一样，请避免直接读取 list 的 `ob_size`。 要改为调用 `PyList_Size()` 函数。）

  `tp_basicsize` 包括类型的 `tp_base` 所需数据大小，加上每个实例所需额外数据的大小。

  设置 `tp_basicsize` 的正确方式是在被用于声明实例布局的结构体上使用 `sizeof` 运算符。 这个结构体必须包括被用于声明基类型的结构体。 换句话说，`tp_basicsize` 必须大于等于基类型的 `tp_basicsize`。

  由于任何类型都是 `object` 的子类型，这个结构体必须包括 `PyObject` 或 `PyVarObject` (具体取决于 `ob_size` 是否应当被包括)。 它们通常是分别由 `PyObject_HEAD` 或 `PyObject_VAR_HEAD` 宏来定义的。

  基础大小不包括 GC 标头大小，因为该标头不是 `PyObject_HEAD` 的一部分。

  对于用于声明基类型的结构体位置未知的情况，请参见 `PyType_Spec.basicsize` 和 `PyType_FromMetaclass()`。

  有关对齐的说明：

  - `tp_basicsize` 必须是 `_Alignof(PyObject)` 的位数。 当如建议的那样在包括了 `PyObject_HEAD` 的 `struct` 上使用 `sizeof` 时，编译器会确保这一点。 当没有使用 C `struct`，或者当使用像 `__attribute__((packed))` 这样的编译器扩展时，这将是你的责任。

  - 如果可变条目需要特定的对齐，则 `tp_basicsize` 和 `tp_itemsize` 必须均为该对齐值的倍数。 举例来说，如果一个类型的可变部分存储了一个 `double`，你就要负责让这两个字段都是 `_Alignof(double)` 的倍数。

  继承：

  这些字段是由子类型分别来继承的。 （也就是说，如果字段被设为零，则 `PyType_Ready()` 将拷贝来自基类型的值，这表示实例不需要额外的存储。）

  如果基类型有一个非零的 `tp_itemsize`，那么在子类型中将 `tp_itemsize` 设置为不同的非零值通常是不安全的（不过这取决于该基类型的具体实现）。

destructor PyTypeObject .tp_dealloc

  The corresponding slot ID `Py_tp_dealloc` is part of the 稳定 ABI.

  一个指向实例析构函数的指针。 函数的签名为:

      void tp_dealloc(PyObject *self);

  析构函数应移除该实例所拥有的所有引用（例如，调用 `Py_CLEAR()`），释放该实例所拥有的所有内存缓冲区，并调用该类型的 `tp_free` 函数来释放对象本身。

  如果您可能会调用那些可能设置错误指示器的函数，则必须使用 `PyErr_GetRaisedException()` 和 `PyErr_SetRaisedException()`，以确保不会破坏已存在的错误指示器（在处理另一个错误的过程中，可能已发生了内存释放）：

      static void
      foo_dealloc(foo_object *self)
      {
          PyObject *et, *ev, *etb;
          PyObject *exc = PyErr_GetRaisedException();
          ...
          PyErr_SetRaisedException(exc);
      }

  释放处理程序本身不应引发异常；若遇到错误情况，应调用 `PyErr_FormatUnraisable()` 记录（并清除）不可抛出的异常。

  关于对象何时被销毁，不做任何保证，除非：

  - Python 会在对象的最后一个引用被删除后立即销毁该对象，或者在一段时间后再销毁，除非其终结器（`tp_finalize`）在此期间重新激活了该对象。

  - 在对象被自动终结（`tp_finalize`）或自动清理（`tp_clear`）的过程中，不会销毁该对象。

  当前 CPython 在引用计数归零时，会立即通过 `Py_DECREF()` 销毁对象，但这一行为在未来版本中可能会改变。

  建议在 `tp_dealloc` 的开头调用 `PyObject_CallFinalizerFromDealloc()` 以确保对象在销毁前始终被终结。

  若该类型支持垃圾回收（即设置了 `Py_TPFLAGS_HAVE_GC` 标志），则析构函数应在清理任何成员字段之前调用 `PyObject_GC_UnTrack()`。

  允许从 `tp_dealloc` 方法中调用 `tp_clear`，以减少代码重复并确保对象在销毁前始终被清理。但需注意，`tp_clear` 可能已被提前调用。

  如果该类型是堆分配的（`Py_TPFLAGS_HEAPTYPE`），则释放器应在调用类型释放器之后，释放对其类型对象的自有引用（通过 `Py_DECREF()`）。参见下面的示例代码。:

      static void
      foo_dealloc(PyObject *op)
      {
         foo_object *self = (foo_object *) op;
         PyObject_GC_UnTrack(self);
         Py_CLEAR(self->ref);
         Py_TYPE(self)->tp_free(self);
      }

  `tp_dealloc` 必须保持异常状态不变。如果它需要调用可能引发异常的函数，必须先备份异常状态，之后（在用 `PyErr_WriteUnraisable()` 记录任何异常后）再恢复该状态。

  示例：

      static void
      foo_dealloc(PyObject *self)
      {
          PyObject *exc = PyErr_GetRaisedException();

          if (PyObject_CallFinalizerFromDealloc(self) < 0) {
              // 自我复活了。
              goto done;
          }

          PyTypeObject *tp = Py_TYPE(self);

          if (tp->tp_flags & Py_TPFLAGS_HAVE_GC) {
              PyObject_GC_UnTrack(self);
          }

          // 可选，但可以避免代码重复，较为方便。
          if (tp->tp_clear && tp->tp_clear(self) < 0) {
              PyErr_WriteUnraisable(self);
          }

          // 此处可执行任何额外的销毁操作。

          tp->tp_free(self);
          self = NULL;  // 若后续调用了 PyErr_WriteUnraisable() 函数。

          if (tp->tp_flags & Py_TPFLAGS_HEAPTYPE) {
              Py_CLEAR(tp);
          }

      done:
          // 可选操作：若之前调用的操作可能引发了异常。
          //
          if (PyErr_Occurred()) {
              PyErr_WriteUnraisable(self);
          }
          PyErr_SetRaisedException(exc);
      }

  `tp_dealloc` 可能从任意 Python 线程调用，而不仅限于创建该对象的线程（如果对象成为引用循环的一部分，该循环可能由任意线程的垃圾回收操作回收）。 这对 Python API 调用不是问题，因为调用 `tp_dealloc` 的线程会带有 attached thread state。然而，如果被销毁的对象反过来会销毁其他 C 库中的对象，则需要确保在调用 `tp_dealloc` 的线程上销毁这些对象不会违反该库的任何假设条件。

  继承：

  此字段会被子类型继承。

  参见

  有关此槽位如何与其他槽位关联的详细信息，请参阅 对象生命周期。

Py_ssize_t PyTypeObject .tp_vectorcall_offset

  一个相对使用 vectorcall 协议 实现调用对象的实例级函数的可选的偏移量，这是一种比简单的 `tp_call` 更有效的替代选择。

  该字段仅在设置了 `Py_TPFLAGS_HAVE_VECTORCALL` 旗标时使用。 在此情况下，它必须为一个包含 `vectorcallfunc` 指针实例中的偏移量的正整数。

  vectorcallfunc 指针可能为 `NULL`，在这种情况下实例的行为就像 `Py_TPFLAGS_HAVE_VECTORCALL` 没有被设置一样：调用实例操作会回退至 `tp_call`。

  任何设置了 `Py_TPFLAGS_HAVE_VECTORCALL` 的类也必须设置 `tp_call` 并确保其行为与 vectorcallfunc 函数一致。 这可以通过将 tp_call 设为 `PyVectorcall_Call()` 来实现。

  在 3.8 版本发生变更: 在 3.8 版之前，这个槽位被命名为 `tp_print`。 在 Python 2.x 中，它被用于打印到文件。 在 Python 3.0 至 3.7 中，它没有被使用。

  在 3.12 版本发生变更: 在 3.12 版之前，不推荐 可变堆类型 实现 vectorcall 协议。 当用户在 Python 代码中设置 `__call__` 时，只有 tp_call 会被更新，很可能使它与 vectorcall 函数不一致。 自 3.12 起，设置 `__call__` 将通过清除 `Py_TPFLAGS_HAVE_VECTORCALL` 旗标来禁用 vectorcall 优化。

  继承：

  该字段总是会被继承。 但是，`Py_TPFLAGS_HAVE_VECTORCALL` 旗标并不总是会被继承。 如果它未被设置，则子类不会使用 vectorcall，除非显式地调用了 `PyVectorcall_Call()`。

getattrfunc PyTypeObject .tp_getattr

  The corresponding slot ID `Py_tp_getattr` is part of the 稳定 ABI.

  一个指向获取属性字符串函数的可选指针。

  该字段已弃用。当它被定义时，应该和 `tp_getattro` 指向同一个函数，但接受一个C字符串参数表示属性名，而不是Python字符串对象。

  继承：

  分组: `tp_getattr`, `tp_getattro`

  该字段会被子类和 `tp_getattro` 所继承：当子类型的 `tp_getattr` 和 `tp_getattro` 均为 `NULL` 时该子类型将从它的基类型同时继承 `tp_getattr` 和 `tp_getattro`。

setattrfunc PyTypeObject .tp_setattr

  The corresponding slot ID `Py_tp_setattr` is part of the 稳定 ABI.

  一个指向函数以便设置和删除属性的可选指针。

  该字段已弃用。当它被定义时，应该和 `tp_setattro` 指向同一个函数，但接受一个C字符串参数表示属性名，而不是Python字符串对象。

  继承：

  分组: `tp_setattr`, `tp_setattro`

  该字段会被子类型和 `tp_setattro` 所继承：当子类型的 `tp_setattr` 和 `tp_setattro` 均为 `NULL` 时该子类型将同时从它的基类型继承 `tp_setattr` 和 `tp_setattro`。

PyAsyncMethods * PyTypeObject .tp_as_async

  指向一个包含仅与在 C 层级上实现 awaitable 和 asynchronous iterator 协议的对象相关联的字段的附加结构体。 请参阅 异步对象结构体 了解详情。

  Added in version 3.5: 在之前被称为 `tp_compare` 和 `tp_reserved`。

  继承：

  `tp_as_async` 字段不会被继承，但所包含的字段会被单独继承。

reprfunc PyTypeObject .tp_repr

  The corresponding slot ID `Py_tp_repr` is part of the 稳定 ABI.

  一个实现了内置函数 `repr()` 的函数的可选指针。

  该签名与 `PyObject_Repr()` 的相同:

      PyObject *tp_repr(PyObject *self);

  该函数必须返回一个字符串或 Unicode 对象。 在理想情况下，该函数应当返回一个字符串，当将其传给 `eval()` 时，只要有合适的环境，就会返回一个具有相同值的对象。 如果这不可行，则它应当返回一个以 `'<'` 开头并以 `'>'` 结尾的可被用来推断出对象的类型和值的字符串。

  继承：

  此字段会被子类型继承。

  默认：

  如果未设置该字段，则返回 `<%s object at %p>` 形式的字符串，其中 `%s` 将替换为类型名称，`%p` 将替换为对象的内存地址。

PyNumberMethods * PyTypeObject .tp_as_number

  指向一个附加结构体的指针，其中包含只与执行数字协议的对象相关的字段。 这些字段的文档参见 数字对象结构体。

  继承：

  `tp_as_number` 字段不会被继承，但所包含的字段会被单独继承。

PySequenceMethods * PyTypeObject .tp_as_sequence

  指向一个附加结构体的指针，其中包含只与执行序列协议的对象相关的字段。 这些字段的文档见 序列对象结构体。

  继承：

  `tp_as_sequence` 字段不会被继承，但所包含的字段会被单独继承。

PyMappingMethods * PyTypeObject .tp_as_mapping

  指向一个附加结构体的指针，其中包含只与执行映射协议的对象相关的字段。 这些字段的文档见 映射对象结构体。

  继承：

  `tp_as_mapping` 字段不会继承，但所包含的字段会被单独继承。

hashfunc PyTypeObject .tp_hash

  The corresponding slot ID `Py_tp_hash` is part of the 稳定 ABI.

  一个指向实现了内置函数 `hash()` 的函数的可选指针。

  其签名与 `PyObject_Hash()` 的相同:

      Py_hash_t tp_hash(PyObject *);

  `-1` 不应作为正常返回值被返回；当计算哈希值过程中发生错误时，函数应设置一个异常并返回 `-1`。

  当该字段（和 `tp_richcompare`）都未设置，尝试对该对象取哈希会引发 `TypeError`。这与将其设为 `PyObject_HashNotImplemented()` 相同。

  此字段可被显式设为 `PyObject_HashNotImplemented()` 以阻止从父类型继承哈希方法。在 Python 层面这被解释为 `__hash__ = None` 的等价物，使得 `isinstance(o, collections.Hashable)` 正确返回 `False`.。请注意反过来也是如此：在 Python 层面设置一个类的 `__hash__ = None` 会使得 `tp_hash` 槽位被设置为 `PyObject_HashNotImplemented()`。

  继承：

  分组: `tp_hash`, `tp_richcompare`

  该字段会被子类型同 `tp_richcompare` 一起继承：当子类型的 `tp_richcompare` 和 `tp_hash` 均为 `NULL` 时子类型将同时继承 `tp_richcompare` 和 `tp_hash`。

  默认：

  `PyBaseObject_Type` 使用 `PyObject_GenericHash()`。

ternaryfunc PyTypeObject .tp_call

  The corresponding slot ID `Py_tp_call` is part of the 稳定 ABI.

  一个可选的实现对象调用的指向函数的指针。 如果对象不是可调用对象则该值应为 `NULL`。 其签名与 `PyObject_Call()` 的相同:

      PyObject *tp_call(PyObject *self, PyObject *args, PyObject *kwargs);

  继承：

  此字段会被子类型继承。

reprfunc PyTypeObject .tp_str

  The corresponding slot ID `Py_tp_str` is part of the 稳定 ABI.

  一个可选的实现内置 `str()` 操作的函数的指针。 （请注意 `str` 现在是一个类型，`str()` 是调用该类型的构造器。 该构造器将调用 `PyObject_Str()` 执行实际操作，而 `PyObject_Str()` 将调用该处理器。）

  其签名与 `PyObject_Str()` 的相同:

      PyObject *tp_str(PyObject *self);

  该函数必须返回一个字符串或 Unicode 对象。 它应当是一个“友好”的对象字符串表示形式，因为这就是要在 `print()` 函数中与其他内容一起使用的表示形式。

  继承：

  此字段会被子类型继承。

  默认：

  当未设置该字段时，将调用 `PyObject_Repr()` 来返回一个字符串表示形式。

getattrofunc PyTypeObject .tp_getattro

  The corresponding slot ID `Py_tp_getattro` is part of the 稳定 ABI.

  一个指向获取属性字符串函数的可选指针。

  其签名与 `PyObject_GetAttr()` 的相同:

      PyObject *tp_getattro(PyObject *self, PyObject *attr);

  可以方便地将该字段设为 `PyObject_GenericGetAttr()`，它实现了查找对象属性的通常方式。

  继承：

  分组: `tp_getattr`, `tp_getattro`

  该字段会被子类同 `tp_getattr` 一起继承：当子类型的 `tp_getattr` 和 `tp_getattro` 均为 `NULL` 时子类型将同时继承 `tp_getattr` 和 `tp_getattro`。

  默认：

  `PyBaseObject_Type` 使用 `PyObject_GenericGetAttr()`。

setattrofunc PyTypeObject .tp_setattro

  The corresponding slot ID `Py_tp_setattro` is part of the 稳定 ABI.

  一个指向函数以便设置和删除属性的可选指针。

  其签名与 `PyObject_SetAttr()` 的相同:

      int tp_setattro(PyObject *self, PyObject *attr, PyObject *value);

  此外，还必须支持将 value 设为 `NULL` 来删除属性。 通常可以方便地将该字段设为 `PyObject_GenericSetAttr()`，它实现了设备对象属性的通常方式。

  继承：

  分组: `tp_setattr`, `tp_setattro`

  该字段会被子类型同 `tp_setattr` 一起继承：当子类型的 `tp_setattr` 和 `tp_setattro` 均为 `NULL` 时子类型将同时继承 `tp_setattr` 和 `tp_setattro`。

  默认：

  `PyBaseObject_Type` 使用 `PyObject_GenericSetAttr()`。

PyBufferProcs * PyTypeObject .tp_as_buffer

  指向一个包含只与实现缓冲区接口的对象相关的字段的附加结构体的指针。 这些字段的文档参见 缓冲区对象结构体。

  继承：

  `tp_as_buffer` 字段不会被继承，但所包含的字段会被单独继承。

unsigned long PyTypeObject .tp_flags

  该字段是针对多个旗标的位掩码。 某些旗标指明用于特定场景的变化语义；另一些旗标则用于指明类型对象（或通过 `tp_as_number`, `tp_as_sequence`, `tp_as_mapping` 和 `tp_as_buffer` 引用的扩展结构体）中的特定字段，它们在历史上并不总是有效；如果这样的旗标位是清晰的，则它所保护的类型字段必须不可被访问并且必须被视为具有零或 `NULL` 值。

  继承：

  此字段的继承较为复杂。大多数标志位是单独继承的，即如果基类型设置了某个标志位，子类型继承该标志位。与扩展结构体相关的标志位在扩展结构体被继承时严格继承，即基类型的标志位值与指向扩展结构体的指针一起复制到子类型中。`Py_TPFLAGS_HAVE_GC` 标志位与 `tp_traverse` 和 `tp_clear` 字段一起继承，即如果子类型中的 `Py_TPFLAGS_HAVE_GC` 标志位未设置，且子类型中的 `tp_traverse` 和 `tp_clear` 字段存在且值为 `NULL`。

  默认：

  `PyBaseObject_Type` 使用 `Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE`。

  位掩码:

  目前定义了以下位掩码；可以使用 `|` 运算符对它们进行 OR 运算以形成 `tp_flags` 字段的值。 宏 `PyType_HasFeature()` 接受一个类型和一个旗标值 tp 和 f，并检查 `tp->tp_flags & f` 是否为非零值。

  Py_TPFLAGS_HEAPTYPE

    当类型对象本身在堆上被分配时会设置这个比特位，例如，使用 `PyType_FromSpec()` 动态创建的类型。 在此情况下，其实例的 `ob_type` 字段会被视为指向该类型的引用，而类型对象将在一个新实例被创建时执行 INCREF，并在实例被销毁时执行 DECREF（这不会应用于子类型的实例；只有实例的 ob_type 所引用的类型会执行 INCREF 和 DECREF）。 堆类型应当也 支持垃圾回收 因为它们会形成对它们自己的模块对象的循环引用。

    继承：

    ？？？

  Py_TPFLAGS_BASETYPE
    属于 稳定 ABI.

    当此类型可被用作另一个类型的基类型时该比特位将被设置。 如果该比特位被清除，则此类型将无法被子类型化（类似于 Java 中的 "final" 类）。

    继承：

    ？？？

  Py_TPFLAGS_READY

    当此类型对象通过 `PyType_Ready()` 被完全实例化时该比特位将被设置。

    继承：

    ？？？

  Py_TPFLAGS_READYING

    当 `PyType_Ready()` 处在初始化此类型对象过程中时该比特位将被设置。

    继承：

    ？？？

  Py_TPFLAGS_HAVE_GC
    属于 稳定 ABI.

    当对象支持垃圾回收时，此比特位被设置。如果设置了此位，新实例（参见 `tp_alloc`）的内存必须使用 `PyObject_GC_New` 或 `PyType_GenericAlloc()` 分配，并使用 `PyObject_GC_Del()` 释放（参见 `tp_free`）。更多信息见 使对象类型支持循环垃圾回收 部分。

    继承：

    分组: `Py_TPFLAGS_HAVE_GC`, `tp_traverse`, `tp_clear`

    `Py_TPFLAGS_HAVE_GC` 旗标位会与 `tp_traverse` 和 `tp_clear` 字段一起被继承，也就是说，如果 `Py_TPFLAGS_HAVE_GC` 旗标位在子类型中被清空并且子类型中的 `tp_traverse` 和 `tp_clear` 字段存在并具有 `NULL` 值的话。

  Py_TPFLAGS_DEFAULT
    属于 稳定 ABI.

    这是一个从属于类型对象及其扩展结构体的存在的所有位的位掩码。 目前，它包括以下的位: `Py_TPFLAGS_HAVE_STACKLESS_EXTENSION`。

    继承：

    ？？？

  Py_TPFLAGS_METHOD_DESCRIPTOR
    属于 稳定 ABI 自 3.8 版起.

    这个位指明对象的行为类似于未绑定方法。

    如果为 `type(meth)` 设置了该旗标，那么：

    - `meth.__get__(obj, cls)(*args, **kwds)` (其中 `obj` 不为 None) 必须等价于 `meth(obj, *args, **kwds)`。

    - `meth.__get__(None, cls)(*args, **kwds)` 必须等价于 `meth(*args, **kwds)`。

    此旗标为 `obj.meth()` 这样的典型方法调用启用优化：它将避免为 `obj.meth` 创建临时的“绑定方法”对象。

    Added in version 3.8.

    继承：

    此旗标绝不会被没有设置 `Py_TPFLAGS_IMMUTABLETYPE` 旗标的类型所继承。 对于扩展类型，当 `tp_descr_get` 被继承时它也会被继承。

  Py_TPFLAGS_MANAGED_DICT

    该比特位指明类的实例具有 `__dict__` 属性，并且该字典的空间是由 VM 管理的。

    如果设置了该旗标，则 `Py_TPFLAGS_HAVE_GC` 也应当被设置。

    类型遍历函数必须调用 `PyObject_VisitManagedDict()` 而它的清空函数必须调用 `PyObject_ClearManagedDict()`。

    Added in version 3.12.

    继承：

    此旗标将被继承，除非某个超类设置了 `tp_dictoffset` 字段。

  Py_TPFLAGS_MANAGED_WEAKREF

    该比特位表示类的实例应当是可被弱引用的。

    Added in version 3.12.

    继承：

    此旗标将被继承，除非某个超类设置了 `tp_weaklistoffset` 字段。

  Py_TPFLAGS_ITEMS_AT_END
    属于 稳定 ABI 自 3.12 版起.

    仅适用于可变大小的类型，也就是说，具有非零 `tp_itemsize` 值的类型。

    表示此类型的实例的可变大小部分位于该实例内存区的末尾，其偏移量为 `Py_TYPE(obj)->tp_basicsize` (每个子类可能不一样)。

    当设置此旗标时，请确保所有子类要么使用此内存布局，要么不是可变大小。 Python 不会检查这一点。

    Added in version 3.12.

    继承：

    这个旗标会被继承。

  Py_TPFLAGS_LONG_SUBCLASS
  Py_TPFLAGS_LIST_SUBCLASS
  Py_TPFLAGS_TUPLE_SUBCLASS
  Py_TPFLAGS_BYTES_SUBCLASS
  Py_TPFLAGS_UNICODE_SUBCLASS
  Py_TPFLAGS_DICT_SUBCLASS
  Py_TPFLAGS_BASE_EXC_SUBCLASS
  Py_TPFLAGS_TYPE_SUBCLASS

    诸如 `PyLong_Check()` 之类的函数将使用这些标志之一调用 `PyType_FastSubclass()`，以快速判断类型是否为内置类型的子类；此类特定检查比通用检查（如 `PyObject_IsInstance()`）更快。继承自内置类型的自定义类型应正确设置其 `tp_flags`，否则与这些类型交互的代码将根据所使用的检查类型表现出不同的行为。

  Py_TPFLAGS_HAVE_FINALIZE

    当类型结构体中存在 `tp_finalize` 槽位时会设置这个比特位。

    Added in version 3.4.

    自 3.8 版本弃用: 此旗标已不再是必要的，因为解释器会假定类型结构体中总是存在 `tp_finalize` 槽位。

  Py_TPFLAGS_HAVE_VECTORCALL
    属于 稳定 ABI 自 3.12 版起.

    当类实现了 vectorcall 协议 时会设置这个比特位。 请参阅 `tp_vectorcall_offset` 了解详情。

    继承：

    如果继承了 `tp_call` 则也会继承这个比特位。

    Added in version 3.8: 同 `_Py_TPFLAGS_HAVE_VECTORCALL`

    在 3.9 版本发生变更.

    重命名为当前名称，不带开头的下划线。 旧的暂定名称已设为 soft deprecated。

    在 3.12 版本发生变更: 现在当类的 `__call__()` 方法被重新赋值时该旗标将从类中移除。

    现在该旗标能被可变类所继承。

  Py_TPFLAGS_IMMUTABLETYPE

    不可变的类型对象会设置这个比特位：类型属性无法被设置或删除。

    `PyType_Ready()` 会自动对 静态类型 应用这个旗标。

    继承：

    这个旗标不会被继承。

    Added in version 3.10.

  Py_TPFLAGS_DISALLOW_INSTANTIATION

    不允许创建此类型的实例：将 `tp_new` 设为 NULL 并且不会在类型字符中创建 `__new__` 键。

    这个旗标必须在创建该类型之前设置，而不是在之后。 例如，它必须在该类型调用 `PyType_Ready()` 之前被设置。

    如果 `tp_base` 为 NULL 或者 `&PyBaseObject_Type` 和 `tp_new` 为 NULL 则该旗标会在 静态类型 上自动设置。

    继承：

    这个旗标不会被继承。 但是，子类将不能被实例化，除非它们提供了不为 NULL 的 `tp_new` (这只能通过 C API 实现)。

    备注

    要禁止直接实例化一个类但允许实例化其子类 (例如对于 abstract base class)，请勿使用此旗标。 替代的做法是，让 `tp_new` 只对子类可用。

    Added in version 3.10.

  Py_TPFLAGS_MAPPING

    这个比特位指明该类的实例可以在被用作 `match` 代码块的目标时匹配映射模式。 它会在注册或子类化 `collections.abc.Mapping` 时自动设置，并在注册 `collections.abc.Sequence` 时取消设置。

    备注

    `Py_TPFLAGS_MAPPING` 和 `Py_TPFLAGS_SEQUENCE` 是互斥的；同时启用两个旗标将导致报错。

    继承：

    这个旗标将被尚未设置 `Py_TPFLAGS_SEQUENCE` 的类型所继承。

    参见

    PEP 634 —— 结构化模式匹配：规范

    Added in version 3.10.

  Py_TPFLAGS_SEQUENCE

    这个比特位指明该类的实例可以在被用作 `match` 代码块的目标时匹配序列模式。 它会在注册或子类化 `collections.abc.Sequence` 时自动设置，并在注册 `collections.abc.Mapping` 时取消设置。

    备注

    `Py_TPFLAGS_MAPPING` 和 `Py_TPFLAGS_SEQUENCE` 是互斥的；同时启用两个旗标将导致报错。

    继承：

    这个旗标将被尚未设置 `Py_TPFLAGS_MAPPING` 的类型所继承。

    参见

    PEP 634 —— 结构化模式匹配：规范

    Added in version 3.10.

  Py_TPFLAGS_VALID_VERSION_TAG

    内部使用。 请不要设置或取消设置此旗标。 用于指明一个类具有被修改的调用 `PyType_Modified()`

    警告

    此旗标存在于头文件中，但未被使用。 它将在未来某个 CPython 版本中被移除。

const char * PyTypeObject .tp_doc

  The corresponding slot ID `Py_tp_doc` is part of the 稳定 ABI.

  一个可选的指向给出该类型对象的文档字符串的以 NUL 结束的 C 字符串的指针。 该指针被暴露为类型和类型实例上的 `__doc__` 属性。

  继承：

  这个字段 不会 被子类型继承。

traverseproc PyTypeObject .tp_traverse

  The corresponding slot ID `Py_tp_traverse` is part of the 稳定 ABI.

  一个可选的指向针对垃圾回收器的遍历函数的指针。 该指针仅会在设置了 `Py_TPFLAGS_HAVE_GC` 旗标位时被使用。 函数签名为:

      int tp_traverse(PyObject *self, visitproc visit, void *arg);

  有关 Python 垃圾回收方案的更多信息可在 使对象类型支持循环垃圾回收 一节中查看。

  `tp_traverse` 指针被垃圾回收器用来检测循环引用。 `tp_traverse` 函数的典型实现会在实例的每个属于该实例所拥有的 Python 对象的成员上简单地调用 `Py_VISIT()`。 例如，以下是来自 `_thread` 扩展模块的函数 `local_traverse()`:

      static int
      local_traverse(PyObject *op, visitproc visit, void *arg)
      {
          localobject *self = (localobject *) op;
          Py_VISIT(self->args);
          Py_VISIT(self->kw);
          Py_VISIT(self->dict);
          return 0;
      }

  请注意 `Py_VISIT()` 仅能在可以参加循环引用的成员上被调用。 虽然还存在一个 `self->key` 成员，但它只能为 `NULL` 或 Python 字符串因而不能成为循环引用的一部分。

  在另一方面，即使你知道某个成员永远不会成为循环引用的一部分，作为调试的辅助你仍然可能想要访问它因此 `gc` 模块的 `get_referents()` 函数将会包括它。

  堆类型 (`Py_TPFLAGS_HEAPTYPE`) 必须这样访问其类型:

      Py_VISIT(Py_TYPE(self));

  它只是从 Python 3.9 开始才需要。 为支持 Python 3.8 和更旧的版本，这一行必须是有条件的:

      #if PY_VERSION_HEX >= 0x03090000
          Py_VISIT(Py_TYPE(self));
      #endif

  如果在 `tp_flags` 字段中设置了 `Py_TPFLAGS_MANAGED_DICT` 比特位，则遍历函数必须这样调用 `PyObject_VisitManagedDict()`:

      PyObject_VisitManagedDict((PyObject*)self, visit, arg);

  警告

  当实现 `tp_traverse` 时，只有实例所 拥有 的成员 (就是有指向它们的 强引用) 才必须被访问。 举例来说，如果一个对象通过 `tp_weaklist` 槽位支持弱引用，那么支持链表 (tp_weaklist 所指向的对象) 的指针就 不能 被访问因为实例并不直接拥有指向自身的弱引用 (弱引用列表被用来支持弱引用机制，但实例没有指向其中的元素的强引用，因为即使实例还存在它们也允许被删除)。

  警告

  遍历函数不能有任何附带影响。 它不能修改任何 Python 对象的引用计数也不能创建或销毁任何 Python 对象。

  请注意 `Py_VISIT()` 要求传给 `local_traverse()` 的 visit 和 arg 形参具有指定的名称；不要随意命名它们。

  堆分配类型 的实例会持有一个指向其类型的引用。 因此它们的遍历函数必须要么访问 `Py_TYPE(self)`，要么通过调用其他堆分配类型（例如一个堆分配超类）的 `tp_traverse` 将此任务委托出去。 如果没有这样做，类型对象可能不会被垃圾回收。

  备注

  `tp_traverse` 函数可以从任何线程调用。

  在 3.9 版本发生变更: 堆分配类型应当访问 `tp_traverse` 中的 `Py_TYPE(self)`。 在较早的 Python 版本中，由于 bug 40217，这样做可能会导致在超类中发生崩溃。

  继承：

  分组: `Py_TPFLAGS_HAVE_GC`, `tp_traverse`, `tp_clear`

  该字段会与 `tp_clear` 和 `Py_TPFLAGS_HAVE_GC` 旗标位一起被子类型所继承：如果旗标位, `tp_traverse` 和 `tp_clear` 在子类型中均为零则它们都将从基类型继承。

inquiry PyTypeObject .tp_clear

  The corresponding slot ID `Py_tp_clear` is part of the 稳定 ABI.

  一个可选的指向清除函数的指针。其签名如下:

      int tp_clear(PyObject *);

  此函数的目的是打破导致 cyclic isolate 的引用循环，以便可以安全地销毁对象。 已清除的对象是部分销毁的对象；该对象不一定要满足正常使用期间保持的设计不变量。

  `tp_clear` 不需要删除不能参与引用循环的对象的引用，例如 Python 字符串或 Python 整数。 然而，清除所有引用可能更方便，并编写类型的 `tp_dealloc` 函数来调用 `tp_clear` 以避免代码重复。（注意 `tp_clear` 可能已经被调用。建议调用幂等函数如 `Py_CLEAR()`。）

  任何非平凡的清理应在 `tp_finalize` 中执行，而不是在 `tp_clear` 中。

  备注

  如果 `tp_clear` 未能打破引用循环，则 cyclic isolate 中的对象可能永远无法回收（“泄漏”）。参见 `gc.garbage`。

  备注

  引用对象（直接和间接）可能已经被清除；它们不一定处于一致状态。

  备注

  `tp_clear` 函数可以从任何线程调用。

  备注

  在调用对象的析构函数（`tp_dealloc`）之前，不能保证对象会自动清除。

  此函数与析构函数（`tp_dealloc`）在以下方面有所不同：

  - 清除对象的目的在于移除可能参与引用循环的其他对象的引用。另一方面，析构函数的目的是一个超集：它必须释放其拥有的 所有 资源，包括不能参与引用循环的对象的引用（例如，整数）以及对象自身的内存（通过调用 `tp_free`）。

  - 当调用 `tp_clear` 时，其他对象可能仍然持有对正在清除的对象的引用。因此，`tp_clear` 不能释放对象自身的内存 (`tp_free`)。另一方面，析构函数只有在不存在（强）引用时才会被调用，因此必须通过释放内存来安全地销毁对象本身。

  - `tp_clear` 可能永远不会自动调用。另一方面，对象的析构函数会在对象变得不可达后的一段时间内自动调用（即，没有对对象的引用，或者对象是 cyclic isolate 的成员）。

  Python 自动清除对象的时间、是否清除以及清除频率没有任何保证，除了以下情况：

  - 如果对象是可达的，即存在对它的引用，并且它不是 cyclic isolate 的成员，Python 不会自动清除该对象。

  - 如果对象尚未自动完成终结（参见 `tp_finalize`），Python 不会自动清除该对象。（如果终结器使对象复活，则在清除之前，对象可能会再次自动完成终结，也可能不会。）

  - 如果对象是 cyclic isolate 的成员，并且循环隔离中的任何成员尚未自动完成终结 (`tp_finalize`)，Python 不会自动清除该对象。

  - Python 会在任何对 `tp_clear` 函数的自动调用返回之后才销毁对象。这确保了在 `tp_clear` 仍在执行时，打破引用循环的行为不会使 `self` 指针失效。

  - Python 不会并发地多次自动调用 `tp_clear`。

  目前 CPython 只在需要打破 cyclic isolate 中的引用循环时自动清除对象，但未来版本可能会在对象销毁之前定期清除对象。

  综合考虑，系统中所有 `tp_clear` 函数必须共同作用以打破所有引用循环。这一点非常微妙，如果有任何疑问，请提供一个 `tp_clear` 函数。例如，元组类型没有实现 `tp_clear` 函数，因为可以证明不可能完全由元组组成引用循环。因此，其他类型的 `tp_clear` 函数负责打破包含元组的任何循环。这并非显而易见，而且通常没有充分的理由不实现 `tp_clear`。

  `tp_clear` 的实现应当丢弃实例指向其成员的可能为 Python 对象的引用，并将指向这些成员的指针设为 `NULL`，如下面的例子所示:

      static int
      local_clear(PyObject *op)
      {
          localobject *self = (localobject *) op;
          Py_CLEAR(self->key);
          Py_CLEAR(self->args);
          Py_CLEAR(self->kw);
          Py_CLEAR(self->dict);
          return 0;
      }

  应当使用 `Py_CLEAR()` 宏，因为清除引用是很微妙的：指向被包含对象的引用必须在指向被包含对象的指针被设为 `NULL` 之后才能被释放 (通过 `Py_DECREF()`)。 这是因为释放引用可能会导致被包含的对象变成垃圾，触发一连串的回收活动，其中可能包括唤起任意 Python 代码 (由于关联到被包含对象的终结器或弱引用回调)。 如果这样的代码有可能再次引用 self，那么这时指向被包含对象的指针为 `NULL` 就是非常重要的，这样 self 就知道被包含对象不可再被使用。 `Py_CLEAR()` 宏将以安全的顺序执行此操作。

  如果在 `tp_flags` 字段中设置了 `Py_TPFLAGS_MANAGED_DICT` 比特位，则 clear 函数必须这样调用 `PyObject_ClearManagedDict()`:

      PyObject_ClearManagedDict((PyObject*)self);

  有关 Python 垃圾回收方案的更多信息可在 使对象类型支持循环垃圾回收 一节中查看。

  继承：

  分组: `Py_TPFLAGS_HAVE_GC`, `tp_traverse`, `tp_clear`

  该字段会与 `tp_traverse` 和 `Py_TPFLAGS_HAVE_GC` 旗标位一起被子类型所继承：如果旗标位, `tp_traverse` 和 `tp_clear` 在子类型中均为零则它们都将从基类型继承。

  参见

  有关此槽位如何与其他槽位关联的详细信息，请参阅 对象生命周期。

richcmpfunc PyTypeObject .tp_richcompare

  The corresponding slot ID `Py_tp_richcompare` is part of the 稳定 ABI.

  一个可选的指向富比较函数的指针，函数的签名为:

      PyObject *tp_richcompare(PyObject *self, PyObject *other, int op);

  第一个形参将保证为 `PyTypeObject` 所定义的类型的实例。

  该函数应当返回比较的结果 (通常为 `Py_True` 或 `Py_False`)。 如果未定义比较运算，它必须返回 `Py_NotImplemented`，如果发生了其他错误则它必须返回 `NULL` 并设置一个异常条件。

  以下常量被定义用作 `tp_richcompare` 和 `PyObject_RichCompare()` 的第三个参数：

  常量 | 对照
  --- | ---

  Py_LT

  `<`

  Py_LE

  `<=`

  Py_EQ

  `==`

  Py_NE

  `!=`

  Py_GT

  `>`

  Py_GE

  `>=`

  定义以下宏是为了简化编写丰富的比较函数：

  Py_RETURN_RICHCOMPARE(VAL_A, VAL_B, op)

    从该函数返回 `Py_True` 或 `Py_False`，这取决于比较的结果。 VAL_A 和 VAL_B 必须是可通过 C 比较运算符进行排序的（例如，它们可以为 C 整数或浮点数）。 第三个参数指明所请求的运算，与 `PyObject_RichCompare()` 的参数一样。

    返回值是一个新的 strong reference。

    发生错误时，将设置异常并从该函数返回 `NULL`。

    Added in version 3.7.

  继承：

  分组: `tp_hash`, `tp_richcompare`

  该字段会被子类型同 `tp_hash` 一起继承：当子类型的 `tp_richcompare` 和 `tp_hash` 均为 `NULL` 时子类型将同时继承 `tp_richcompare` 和 `tp_hash`。

  默认：

  `PyBaseObject_Type` 提供了一个 `tp_richcompare` 的实现，它可以被继承。 但是，如果只定义了 `tp_hash`，则不会使用被继承的函数并且该类型的实例将无法参加任何比较。

Py_ssize_t PyTypeObject .tp_weaklistoffset

  虽然此字段仍然受到支持，但是如果可能就应当改用 `Py_TPFLAGS_MANAGED_WEAKREF`。

  如果此类型的实例是可被弱引用的，则该字段将大于零并包含在弱引用列表头的实例结构体中的偏移量（忽略 GC 头，如果存在的话）；该偏移量将被 `PyObject_ClearWeakRefs()` 和 `PyWeakref_*` 函数使用。 实例结构体需要包括一个 PyObject * 类型的字段并初始化为 `NULL`。

  不要将该字段与 `tp_weaklist` 混淆；后者是指向类型对象本身的弱引用的列表头。

  同时设置 `Py_TPFLAGS_MANAGED_WEAKREF` 位和 `tp_weaklistoffset` 将导致错误。

  继承：

  该字段会被子类型继承，但注意参阅下面列出的规则。 子类型可以覆盖此偏移量；这意味着子类型将使用不同于基类型的弱引用列表。 由于列表头总是通过 `tp_weaklistoffset` 找到的，所以这应该不成问题。

  默认：

  如果在 `tp_flags` 字段中设置了 `Py_TPFLAGS_MANAGED_WEAKREF` 位，则 `tp_weaklistoffset` 将被设为负值，用以表明使用此字段是不安全的。

getiterfunc PyTypeObject .tp_iter

  The corresponding slot ID `Py_tp_iter` is part of the 稳定 ABI.

  一个可选的指向函数的指针，该函数返回对象的 iterator。 它的存在通常表明该类型的实例为 iterable (尽管序列在没有此函数的情况下也可能为可迭代对象)。

  此函数的签名与 `PyObject_GetIter()` 的相同:

      PyObject *tp_iter(PyObject *self);

  继承：

  此字段会被子类型继承。

iternextfunc PyTypeObject .tp_iternext

  The corresponding slot ID `Py_tp_iternext` is part of the 稳定 ABI.

  一个可选的指向函数的指针，该函数返回 iterator 中的下一项。 其签名为:

      PyObject *tp_iternext(PyObject *self);

  当该迭代器被耗尽时，它必须返回 `NULL`；`StopIteration` 异常可能会设置也可能不设置。 当发生另一个错误时，它也必须返回 `NULL`。 它的存在表明该类型的实际是迭代器。

  迭代器类型也应当定义 `tp_iter` 函数，并且该函数应当返回迭代器实例本身（而不是新的迭代器实例）。

  此函数的签名与 `PyIter_Next()` 的相同。

  继承：

  此字段会被子类型继承。

struct PyMethodDef * PyTypeObject .tp_methods

  The corresponding slot ID `Py_tp_methods` is part of the 稳定 ABI.

  一个可选的指向 `PyMethodDef` 结构体的以 `NULL` 结束的静态数组的指针，它声明了此类型的常规方法。

  对于该数组中的每一项，都会向类型的字典 (参见下面的 `tp_dict`) 添加一个包含方法描述器的条目。

  继承：

  该字段不会被子类型所继承（方法是通过不同的机制来继承的）。

struct PyMemberDef * PyTypeObject .tp_members

  The corresponding slot ID `Py_tp_members` is part of the 稳定 ABI.

  一个可选的指向 `PyMemberDef` 结构体的以 `NULL` 结束的静态数组的指针，它声明了此类型的常规数据成员（字段或槽位）。

  对于该数组中的每一项，都会向类型的字典 (参见下面的 `tp_dict`) 添加一个包含方法描述器的条目。

  继承：

  该字段不会被子类型所继承（成员是通过不同的机制来继承的）。

struct PyGetSetDef * PyTypeObject .tp_getset

  The corresponding slot ID `Py_tp_getset` is part of the 稳定 ABI.

  一个可选的指向 `PyGetSetDef` 结构体的以 `NULL` 结束的静态数组的指针，它声明了此类型的实例中的被计算属性。

  对于该数组中的每一项，都会向类型的字典 (参见下面的 `tp_dict`) 添加一个包含读写描述器的条目。

  继承：

  该字段不会被子类型所继承（被计算属性是通过不同的机制来继承的）。

PyTypeObject * PyTypeObject .tp_base

  The corresponding slot ID `Py_tp_base` is part of the 稳定 ABI.

  一个可选的指向类型特征属性所继承的基类型的指针。 在这个层级上，只支持单继承；多重继承需要通过调用元类型动态地创建类型对象。

  备注

  槽位初始化需要遵循初始化全局变量的规则。 C99 要求初始化器为“地址常量”。 隐式转换为指针的函数指示器如 `PyType_GenericNew()` 都是有效的 C99 地址常量。

  但是，生成地址常量并不需要应用于非静态变量如 `PyBaseObject_Type` 的单目运算符 '&'。 编译器可能支持该运算符（如 gcc），但 MSVC 则不支持。 这两种编译器在这一特定行为上都是严格符合标准的。

  因此，应当在扩展模块的初始化函数中设置 `tp_base`。

  继承：

  该字段不会被子类型继承（显然）。

  默认：

  该字段默认为 `&PyBaseObject_Type` (对 Python 程序员来说即 `object` 类型)。

PyObject * PyTypeObject .tp_dict

  类型的字典将由 `PyType_Ready()` 存储到这里。

  该字段通常应当在 PyType_Ready 被调用之前初始化为 `NULL`；它也可以初始化为一个包含类型初始属性的字典。 一旦 `PyType_Ready()` 完成类型的初始化，该类型的额外属性只有在它们不与被重载的操作 (如 `__add__()`) 相对应的情况下才会被添加到该字典中。 一旦类型的初始化结束，该字段就应被视为是只读的。

  某些类型不会将它们的字典存储在该槽位中。 请使用 `PyType_GetDict()` 来获取任意类型对应的字典。

  在 3.12 版本发生变更: 内部细节：对于静态内置类型，该值总是为 `NULL`。 这种类型的字典是存储在 `PyInterpreterState` 中。 请使用 `PyType_GetDict()` 来获取任意类型的字典。

  继承：

  该字段不会被子类型所继承（但在这里定义的属性是通过不同的机制来继承的）。

  默认：

  如果该字段为 `NULL`，`PyType_Ready()` 将为它分配一个新字典。

  警告

  通过字典 C-API 使用 `PyDict_SetItem()` 或修改 `tp_dict` 是不安全的。

descrgetfunc PyTypeObject .tp_descr_get

  The corresponding slot ID `Py_tp_descr_get` is part of the 稳定 ABI.

  一个可选的指向“描述器获取”函数的指针。

  函数的签名为:

      PyObject * tp_descr_get(PyObject *self, PyObject *obj, PyObject *type);

  继承：

  此字段会被子类型继承。

descrsetfunc PyTypeObject .tp_descr_set

  The corresponding slot ID `Py_tp_descr_set` is part of the 稳定 ABI.

  一个指向用于设置和删除描述器值的函数的选项指针。

  函数的签名为:

      int tp_descr_set(PyObject *self, PyObject *obj, PyObject *value);

  将 value 参数设为 `NULL` 以删除该值。

  继承：

  此字段会被子类型继承。

Py_ssize_t PyTypeObject .tp_dictoffset

  虽然此字段仍然受到支持，但是如果可能就应当改用 `Py_TPFLAGS_MANAGED_DICT`。

  如果该类型的实例具有一个包含实例变量的字典，则此字段将为非零值并包含该实例变量字典的类型的实例的偏移量；该偏移量将由 `PyObject_GenericGetAttr()` 使用。

  不要将该字段与 `tp_dict` 混淆；后者是由类型对象本身的属性组成的字典。

  该值指定字典相对实例结构体开始位置的偏移量。

  `tp_dictoffset` 应当被视为是只读的。 用于获取指向字典调用 `PyObject_GenericGetDict()` 的指针。 调用 `PyObject_GenericGetDict()` 可能需要为字典分配内存，因此在访问对象上的属性时调用 `PyObject_GetAttr()` 可能会更有效率。

  同时设置 `Py_TPFLAGS_MANAGED_DICT` 位和 `tp_dictoffset` 将导致报错。

  继承：

  该字段会被子类型所继承。 子类型不应重写这个偏移量；这样做是不安全的，如果 C 代码试图在之前的偏移量上访问字典的话。 要正确地支持继承，请使用 `Py_TPFLAGS_MANAGED_DICT`。

  默认：

  这个槽位没有默认值。 对于 静态类型，如果该字段为 `NULL` 则不会为实例创建 `__dict__`。

  如果在 `tp_flags` 字段中设置了 `Py_TPFLAGS_MANAGED_DICT` 比特位，则 `tp_dictoffset` 将被设为 `-1`，以表明使用该字段是不安全的。

initproc PyTypeObject .tp_init

  The corresponding slot ID `Py_tp_init` is part of the 稳定 ABI.

  一个可选的指向实例初始化函数的指针。

  此函数对应于类的 `__init__()` 方法。 和 `__init__()` 一样，创建实例时不调用 `__init__()` 是有可能的，并且通过再次调用实例的 `__init__()` 方法将其重新初始化也是有可能的。

  函数的签名为:

      int tp_init(PyObject *self, PyObject *args, PyObject *kwds);

  self 参数是将要初始化的实例；args 和 kwds 参数代表调用 `__init__()` 时传入的位置和关键字参数。

  `tp_init` 函数如果不为 `NULL`，将在通过调用类型正常创建其实例时被调用，即在类型的 `tp_new` 函数返回一个该类型的实例时。 如果 `tp_new` 函数返回了一个不是原始类型的子类型的其他类型的实例，则 `tp_init` 函数不会被调用；如果 `tp_new` 返回了一个原始类型的子类型的实例，则该子类型的 `tp_init` 将被调用。

  成功时返回 `0`，发生错误时则返回 `-1` 并在错误上设置一个异常。and sets an exception on error.

  继承：

  此字段会被子类型继承。

  默认：

  对于 静态类型 来说该字段没有默认值。

allocfunc PyTypeObject .tp_alloc

  The corresponding slot ID `Py_tp_alloc` is part of the 稳定 ABI.

  指向一个实例分配函数的可选指针。

  函数的签名为:

      PyObject *tp_alloc(PyTypeObject *self, Py_ssize_t nitems);

  继承：

  静态子类型继承此槽位，如果从 `object` 继承，则此槽位为 `PyType_GenericAlloc()`。

  堆子类型 不继承此槽位。

  默认：

  对于堆子类型，此字段始终设置为 `PyType_GenericAlloc()`。

  对于静态子类型，此槽位是继承的（见上文）。

newfunc PyTypeObject .tp_new

  The corresponding slot ID `Py_tp_new` is part of the 稳定 ABI.

  一个可选的指向实例创建函数的指针。

  函数的签名为:

      PyObject *tp_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds);

  subtype 参数是被创建的对象的类型；args 和 kwds 参数表示调用类型时传入的位置和关键字参数。 请注意 subtype 不是必须与被调用的 `tp_new` 函数所属的类型相同；它可以是该类型的子类型（但不能是完全无关的类型）。

  `tp_new` 函数应当调用 `subtype->tp_alloc(subtype, nitems)` 来为对象分配空间，然后只执行绝对有必要的进一步初始化操作。 可以安全地忽略或重复的初始化操作应当放在 `tp_init` 处理器中。 一个关键的规则是对于不可变类型来说，所有初始化操作都应当在 `tp_new` 中发生，而对于可变类型，大部分初始化操作都应当推迟到 `tp_init` 再执行。

  设置 `Py_TPFLAGS_DISALLOW_INSTANTIATION` 旗标以禁止在 Python 中创建该类型的实例。

  继承：

  该字段会被子类型所继承，例外情况是它不会被 `tp_base` 为 `NULL` 或 `&PyBaseObject_Type` 的 静态类型 所继承。

  默认：

  对于 静态类型 该字段没有默认值。 这意味着如果槽位被定义为 `NULL`，则无法调用此类型来创建新的实例；应当存在 其他办法来创建实例，例如工厂函数等。

freefunc PyTypeObject .tp_free

  The corresponding slot ID `Py_tp_free` is part of the 稳定 ABI.

  一个可选的指向实例释放函数的指针。 函数的签名为:

      void tp_free(void *self);

  此函数必须释放由 `tp_alloc` 分配的内存。

  继承：

  静态子类型继承此槽位，如果从 `object` 继承，则此槽位为 `PyObject_Free()`。例外情况：如果类型支持垃圾回收（即 `tp_flags` 中设置了 `Py_TPFLAGS_HAVE_GC` 标志），并且它将继承 `PyObject_Free()`，则此槽位不继承，而是默认为 `PyObject_GC_Del()`。

  堆子类型 不继承此槽位。

  默认：

  对于 堆子类型，此槽位默认为一个适合匹配 `PyType_GenericAlloc()` 和 `Py_TPFLAGS_HAVE_GC` 标志值的释放器。

  对于静态子类型，此槽位是继承的（见上文）。

inquiry PyTypeObject .tp_is_gc

  The corresponding slot ID `Py_tp_is_gc` is part of the 稳定 ABI.

  可选的指向垃圾回收器所调用的函数的指针。

  垃圾回收器需要知道某个特定的对象是否可以被回收。在一般情况下，垃圾回收器只需要检查这个对象类型的 `tp_flags` 字段、以及 `Py_TPFLAGS_HAVE_GC` 标识位即可做出判断；但是有一些类型同时混合包含了静态和动态分配的实例，其中静态分配的实例不应该也无法被回收。本函数为后者情况而设计：对于可被垃圾回收的实例，本函数应当返回 `1` ；对于不可被垃圾回收的实例，本函数应当返回 `0` 。函数的签名为:

      int tp_is_gc(PyObject *self);

  （此对象的唯一样例是类型本身。 元类型 `PyType_Type` 定义了该函数来区分静态和 动态分配的类型。）

  继承：

  此字段会被子类型继承。

  默认：

  此槽位没有默认值。 如果该字段为 `NULL`，则将使用 `Py_TPFLAGS_HAVE_GC` 作为相同功能的替代。

PyObject * PyTypeObject .tp_bases

  The corresponding slot ID `Py_tp_bases` is part of the 稳定 ABI.

  基类型的元组。

  此字段应当被设为 `NULL` 并被视为只读。 Python 将在类型 `初始化时` 填充它。

  对于动态创建的类，可以使用 `Py_tp_bases` `槽位` 来代替 `PyType_FromSpecWithBases()` 的 bases 参数。 推荐使用参数形式。

  警告

  多重继承不适合静态定义的类型。 如果你将 `tp_bases` 设为一个元组，Python 将不会引发错误，但某些槽位将只从第一个基类型继承。

  继承：

  这个字段不会被继承。

PyObject * PyTypeObject .tp_mro

  包含基类型的扩展集的元组，以类型本身开始并以 `object` 作为结束，使用方法解析顺序。

  此字段应当被设为 `NULL` 并被视为只读。 Python 将在类型 `初始化时` 填充它。

  继承：

  这个字段不会被继承；它是通过 `PyType_Ready()` 计算得到的。

PyObject * PyTypeObject .tp_cache

  尚未使用。 仅供内部使用。

  继承：

  这个字段不会被继承。

void * PyTypeObject .tp_subclasses

  一组子类。 仅限内部使用的。 可能为无效的指针。

  要获取子类的列表，则调用 Python 方法 `__subclasses__()`。

  在 3.12 版本发生变更: 对于某些类型，该字段将不带有效的 PyObject *。 类型已被改为 void* 以指明这一点。

  继承：

  这个字段不会被继承。

PyObject * PyTypeObject .tp_weaklist

  弱引用列表头，用于指向该类型对象的弱引用。 不会被继承。 仅限内部使用。

  在 3.12 版本发生变更: 内部细节：对于静态内置类型这将总是为 `NULL`，即使添加了弱引用也是如此。 每个弱引用都转而保存在 `PyInterpreterState` 上。 请使用公共 C-API 或内部 `_PyObject_GET_WEAKREFS_LISTPTR()` 宏来避免此差异。

  继承：

  这个字段不会被继承。

destructor PyTypeObject .tp_del

  The corresponding slot ID `Py_tp_del` is part of the 稳定 ABI.

  该字段已被弃用。 请改用 `tp_finalize`。

unsigned int PyTypeObject .tp_version_tag

  用于索引至方法缓存。 仅限内部使用。

  继承：

  这个字段不会被继承。

destructor PyTypeObject .tp_finalize

  The corresponding slot ID `Py_tp_finalize` is part of the 稳定 ABI 自 3.5 版起.

  一个可选的指向实例终结函数的指针。这是 `__del__()` 特殊方法的 C 实现。其签名如下:

      void tp_finalize(PyObject *self);

  终结器的主要目的是在对象被销毁之前执行任何必须进行的非平凡的清理工作——此时对象及其直接或间接引用的任何其他对象仍处于一致状态。终结器允许执行任意的Python代码。

  在Python自动终结一个对象之前，该对象的一些直接或间接引用对象可能已经自动终结。然而，这些引用对象尚未被自动清除（`tp_clear`）。

  其他未终结的对象可能仍在使用已终结的对象，因此终结器必须确保该对象保持合理状态（例如，仍满足所有不变式条件）。

  备注

  在Python自动终结一个对象之后，Python可能会开始自动清除（`tp_clear`）该对象及其（直接和间接）引用对象。被清除的对象不保证处于一致状态；已终结的对象必须能够容忍被清除的引用对象。

  备注

  不保证在对象的析构函数（`tp_dealloc`）被调用之前自动终结对象。建议在 `tp_dealloc` 的开始处调用 `PyObject_CallFinalizerFromDealloc()`，以确保在销毁之前总是终结对象。

  备注

  `tp_finalize` 函数可以从任何线程调用，尽管 GIL 会被持有。

  备注

  `tp_finalize` 函数可以在关闭过程中调用，此时一些全局变量可能已被删除。 详见 `__del__()` 方法的文档。

  当Python终结一个对象时，其行为类似于以下算法：

  1. Python可能会将对象标记为 已终结。目前，Python总是标记那些其类型支持垃圾收集的对象（即，`Py_TPFLAGS_HAVE_GC` 标志在 `tp_flags` 中设置）并且从不标记其他类型的对象；这一点在未来版本中可能会改变。

  2. 如果对象未被标记为 已终结 且其 `tp_finalize` 终结器函数不为 `NULL`，则会调用该终结器函数。

  3. 如果终结器函数被调用并且终结器使对象变得可达（即，存在对该对象的引用且它不是 cyclic isolate 的成员），则称终结器 复活 了该对象。若终结器通过添加新引用使对象变为可达（但该对象仍属于某个循环隔离），则是否算作复活行为是未定义的。

  4. 如果终结器复活了对象，对象的待销毁状态将被取消，并且如果存在，对象的 已终结 标记可能会被移除。目前，Python从不移除 已终结 标记；这一点在未来版本中可能会改变。

  自动终结 指的是由Python执行的任何终结操作，但不包括通过调用 `PyObject_CallFinalizer()` 或 `PyObject_CallFinalizerFromDealloc()` 进行的终结。关于对象何时、是否或多久被自动终结一次，没有任何保证，除了：

  - 如果对象是可达的，即存在对它的引用且它不是 cyclic isolate 的成员，Python 不会自动终结该对象。

  - 如果终结对象不会将其标记为 已终结，Python也不会自动终结该对象。目前，这适用于那些其类型不支持垃圾收集的对象，即 `Py_TPFLAGS_HAVE_GC` 标志未设置。此类对象仍然可以通过调用 `PyObject_CallFinalizer()` 或 `PyObject_CallFinalizerFromDealloc()` 进行手动终结。

  - Python 不会自动并发地终结 cyclic isolate 的任意两个成员。

  - Python 不会在自动清除（`tp_clear`）对象后自动终结该对象。

  - 如果一个对象是 cyclic isolate 的成员，Python 不会在自动清除 (参见 `tp_clear`) 其他成员后自动终结它。

  - Python 会在自动清除 (参见 `tp_clear`) 任何成员之前，自动终结 cyclic isolate 的所有成员。

  - 如果 Python 将要自动清除一个对象（`tp_clear`），它将首先自动终结该对象。

  目前 Python 只会自动终结属于 cyclic isolate 的成员对象，但未来版本可能会在对象销毁前常规性地终结对象。

  要手动终结一个对象，请勿直接调用此函数；而应调用 `PyObject_CallFinalizer()` 或 `PyObject_CallFinalizerFromDealloc()`。

  `tp_finalize` 应保持当前异常状态不变。编写非平凡终结器的推荐方法是，在开始时通过调用 `PyErr_GetRaisedException()` 备份异常，并在结束时通过调用 `PyErr_SetRaisedException()` 恢复异常。如果在终结器中间遇到异常，请使用 `PyErr_WriteUnraisable()` 或 `PyErr_FormatUnraisable()` 记录并清除它。例如：

      static void
      foo_finalize(PyObject *self)
      {
          // 保存当前异常（如果有）。
          PyObject *exc = PyErr_GetRaisedException();

          // ...

          if (do_something_that_might_raise() != success_indicator) {
              PyErr_WriteUnraisable(self);
              goto done;
          }

      done:
          // 恢复保存的异常。这将静默丢弃上述任何异常，
          // 因此在必要时请先调用 PyErr_WriteUnraisable。
          PyErr_SetRaisedException(exc);
      }

  继承：

  此字段会被子类型继承。

  Added in version 3.4.

  在 3.8 版本发生变更: 在 3.8 版之前必须设置 `Py_TPFLAGS_HAVE_FINALIZE` 标志信才能让该字段被使用。 现在已不再需要这样做。

  参见

  - PEP 442: "安全对象终结"

  - 有关此槽位如何与其他槽位关联的详细信息，请参阅 对象生命周期。

  - `PyObject_CallFinalizer()`

  - `PyObject_CallFinalizerFromDealloc()`

vectorcallfunc PyTypeObject .tp_vectorcall

  The corresponding slot ID `Py_tp_vectorcall` is part of the 稳定 ABI 自 3.14 版起.

  用于此类型对象（而不是实例）调用的 vectorcall 函数。 换句话说，`tp_vectorcall` 可以用来优化 `type.__call__`，这通常会返回 type 的新实例。

  与任何 vectorcall 函数一样，如果 `tp_vectorcall` 为 `NULL`，则使用 tp_call 协议（`Py_TYPE(type)->tp_call`）。

  备注

  vectorcall 协议 要求 vectorcall 函数具有与相应的 `tp_call` 相同的行为。这意味着 `type->tp_vectorcall` 必须与 `Py_TYPE(type)->tp_call` 的行为相匹配。

  具体来说，如果 type 使用默认的元类，`type->tp_vectorcall` 的行为必须与 PyType_Type ->tp_call 相同：

  - 调用 `type->tp_new`，

  - 当结果是 type 的子类时，将在 `tp_new` 的结果上调用 `type->tp_init`，并且

  - 返回 `tp_new` 的结果。

  通常，`tp_vectorcall` 会被重写以针对特定的 `tp_new` 和 `tp_init` 优化此进程。当为可被用户子类化的类型上这样做时，请注意两者都可被重写 (分别使用 `__new__()` 和 `__init__()`)。

  继承：

  这个字段不会被继承。

  Added in version 3.9: （这个字段从 3.8 起即存在，但是从 3.9 开始投入使用）

unsigned char PyTypeObject .tp_watched

  内部对象。 请勿使用。

  Added in version 3.12.

## 静态类型

在传统上，在 C 代码中定义的类型都是 静态的，也就是说，`PyTypeObject` 结构体在代码中直接定义并使用 `PyType_Ready()` 来初始化。

这就导致了与在 Python 中定义的类型相关联的类型限制：

- 静态类型只能拥有一个基类；换句话说，他们不能使用多重继承。

- 静态类型对象（但并非它们的实例）是不可变对象。 不可能在 Python 中添加或修改类型对象的属性。

- 静态类型对象是跨 子解释器 共享的，因此它们不应包括任何子解释器专属的状态。

此外，由于 `PyTypeObject` 只是作为不透明结构的 受限 API 的一部分，因此任何使用静态类型的扩展模块都必须针对特定的 Python 次版本进行编译。

## 堆类型

一种 静态类型的 替代物是 堆分配类型，或者简称 堆类型，它与使用 Python 的 `class` 语句创建的类紧密对应。 堆类型设置了 `Py_TPFLAGS_HEAPTYPE` 旗标。

这是通过填充 `PyType_Spec` 结构体并调用 `PyType_FromSpec()`, `PyType_FromSpecWithBases()`, `PyType_FromModuleAndSpec()` 或 `PyType_FromMetaclass()` 来实现的。

## 数字对象结构体

type PyNumberMethods

  该结构体持有指向被对象用来实现数字协议的函数的指针。 每个函数都被 数字协议 一节中记录的对应名称的函数所使用。

  结构体定义如下:

      typedef struct {
           binaryfunc nb_add;
           binaryfunc nb_subtract;
           binaryfunc nb_multiply;
           binaryfunc nb_remainder;
           binaryfunc nb_divmod;
           ternaryfunc nb_power;
           unaryfunc nb_negative;
           unaryfunc nb_positive;
           unaryfunc nb_absolute;
           inquiry nb_bool;
           unaryfunc nb_invert;
           binaryfunc nb_lshift;
           binaryfunc nb_rshift;
           binaryfunc nb_and;
           binaryfunc nb_xor;
           binaryfunc nb_or;
           unaryfunc nb_int;
           void *nb_reserved;
           unaryfunc nb_float;

           binaryfunc nb_inplace_add;
           binaryfunc nb_inplace_subtract;
           binaryfunc nb_inplace_multiply;
           binaryfunc nb_inplace_remainder;
           ternaryfunc nb_inplace_power;
           binaryfunc nb_inplace_lshift;
           binaryfunc nb_inplace_rshift;
           binaryfunc nb_inplace_and;
           binaryfunc nb_inplace_xor;
           binaryfunc nb_inplace_or;

           binaryfunc nb_floor_divide;
           binaryfunc nb_true_divide;
           binaryfunc nb_inplace_floor_divide;
           binaryfunc nb_inplace_true_divide;

           unaryfunc nb_index;

           binaryfunc nb_matrix_multiply;
           binaryfunc nb_inplace_matrix_multiply;
      } PyNumberMethods;

  备注

  双目和三目函数必须检查其所有操作数的类型，并实现必要的转换（至少有一个操作数是所定义类型的实例）。 如果没有为所给出的操作数定义操作，则双目和三目函数必须返回 `Py_NotImplemented`，如果发生了其他错误则它们必须返回 `NULL` 并设置一个异常。

  备注

  `nb_reserved` 字段应当始终为 `NULL`。 在之前版本中其名称为 `nb_long`，并在 Python 3.0.1 中改名。

binaryfunc PyNumberMethods .nb_add

  The corresponding slot ID `Py_nb_add` is part of the 稳定 ABI.

binaryfunc PyNumberMethods .nb_subtract

  The corresponding slot ID `Py_nb_subtract` is part of the 稳定 ABI.

binaryfunc PyNumberMethods .nb_multiply

  The corresponding slot ID `Py_nb_multiply` is part of the 稳定 ABI.

binaryfunc PyNumberMethods .nb_remainder

  The corresponding slot ID `Py_nb_remainder` is part of the 稳定 ABI.

binaryfunc PyNumberMethods .nb_divmod

  The corresponding slot ID `Py_nb_divmod` is part of the 稳定 ABI.

ternaryfunc PyNumberMethods .nb_power

  The corresponding slot ID `Py_nb_power` is part of the 稳定 ABI.

unaryfunc PyNumberMethods .nb_negative

  The corresponding slot ID `Py_nb_negative` is part of the 稳定 ABI.

unaryfunc PyNumberMethods .nb_positive

  The corresponding slot ID `Py_nb_positive` is part of the 稳定 ABI.

unaryfunc PyNumberMethods .nb_absolute

  The corresponding slot ID `Py_nb_absolute` is part of the 稳定 ABI.

inquiry PyNumberMethods .nb_bool

  The corresponding slot ID `Py_nb_bool` is part of the 稳定 ABI.

unaryfunc PyNumberMethods .nb_invert

  The corresponding slot ID `Py_nb_invert` is part of the 稳定 ABI.

binaryfunc PyNumberMethods .nb_lshift

  The corresponding slot ID `Py_nb_lshift` is part of the 稳定 ABI.

binaryfunc PyNumberMethods .nb_rshift

  The corresponding slot ID `Py_nb_rshift` is part of the 稳定 ABI.

binaryfunc PyNumberMethods .nb_and

  The corresponding slot ID `Py_nb_and` is part of the 稳定 ABI.

binaryfunc PyNumberMethods .nb_xor

  The corresponding slot ID `Py_nb_xor` is part of the 稳定 ABI.

binaryfunc PyNumberMethods .nb_or

  The corresponding slot ID `Py_nb_or` is part of the 稳定 ABI.

unaryfunc PyNumberMethods .nb_int

  The corresponding slot ID `Py_nb_int` is part of the 稳定 ABI.

void * PyNumberMethods .nb_reserved

unaryfunc PyNumberMethods .nb_float

  The corresponding slot ID `Py_nb_float` is part of the 稳定 ABI.

binaryfunc PyNumberMethods .nb_inplace_add

  The corresponding slot ID `Py_nb_inplace_add` is part of the 稳定 ABI.

binaryfunc PyNumberMethods .nb_inplace_subtract

  The corresponding slot ID `Py_nb_inplace_subtract` is part of the 稳定 ABI.

binaryfunc PyNumberMethods .nb_inplace_multiply

  The corresponding slot ID `Py_nb_inplace_multiply` is part of the 稳定 ABI.

binaryfunc PyNumberMethods .nb_inplace_remainder

  The corresponding slot ID `Py_nb_inplace_remainder` is part of the 稳定 ABI.

ternaryfunc PyNumberMethods .nb_inplace_power

  The corresponding slot ID `Py_nb_inplace_power` is part of the 稳定 ABI.

binaryfunc PyNumberMethods .nb_inplace_lshift

  The corresponding slot ID `Py_nb_inplace_lshift` is part of the 稳定 ABI.

binaryfunc PyNumberMethods .nb_inplace_rshift

  The corresponding slot ID `Py_nb_inplace_rshift` is part of the 稳定 ABI.

binaryfunc PyNumberMethods .nb_inplace_and

  The corresponding slot ID `Py_nb_inplace_and` is part of the 稳定 ABI.

binaryfunc PyNumberMethods .nb_inplace_xor

  The corresponding slot ID `Py_nb_inplace_xor` is part of the 稳定 ABI.

binaryfunc PyNumberMethods .nb_inplace_or

  The corresponding slot ID `Py_nb_inplace_or` is part of the 稳定 ABI.

binaryfunc PyNumberMethods .nb_floor_divide

  The corresponding slot ID `Py_nb_floor_divide` is part of the 稳定 ABI.

binaryfunc PyNumberMethods .nb_true_divide

  The corresponding slot ID `Py_nb_true_divide` is part of the 稳定 ABI.

binaryfunc PyNumberMethods .nb_inplace_floor_divide

  The corresponding slot ID `Py_nb_inplace_floor_divide` is part of the 稳定 ABI.

binaryfunc PyNumberMethods .nb_inplace_true_divide

  The corresponding slot ID `Py_nb_inplace_true_divide` is part of the 稳定 ABI.

unaryfunc PyNumberMethods .nb_index

  The corresponding slot ID `Py_nb_index` is part of the 稳定 ABI.

binaryfunc PyNumberMethods .nb_matrix_multiply

  The corresponding slot ID `Py_nb_matrix_multiply` is part of the 稳定 ABI 自 3.5 版起.

binaryfunc PyNumberMethods .nb_inplace_matrix_multiply

  The corresponding slot ID `Py_nb_inplace_matrix_multiply` is part of the 稳定 ABI 自 3.5 版起.

## 映射对象结构体

type PyMappingMethods

  该结构体持有指向对象用于实现映射协议的函数的指针。 它有三个成员：

lenfunc PyMappingMethods .mp_length

  The corresponding slot ID `Py_mp_length` is part of the 稳定 ABI.

  该函数将被 `PyMapping_Size()` 和 `PyObject_Size()` 使用，并具有相同的签名。 如果对象没有定义长度则此槽位可被设为 `NULL`。

binaryfunc PyMappingMethods .mp_subscript

  The corresponding slot ID `Py_mp_subscript` is part of the 稳定 ABI.

  该函数将被 `PyObject_GetItem()` 和 `PySequence_GetSlice()` 使用，并具有与 `PyObject_GetItem()` 相同的签名。 此槽位必须被填充以便 `PyMapping_Check()` 函数返回 `1`，否则它可以为 `NULL`。

objobjargproc PyMappingMethods .mp_ass_subscript

  The corresponding slot ID `Py_mp_ass_subscript` is part of the 稳定 ABI.

  该函数将被 `PyObject_SetItem()`, `PyObject_DelItem()`, `PySequence_SetSlice()` 和 `PySequence_DelSlice()` 使用。 它具有与 `PyObject_SetItem()` 相同的签名，但 v 也可以被设为 `NULL` 以删除一个条目。 如果此槽位为 `NULL`，则对象将不支持条目赋值和删除。

## 序列对象结构体

type PySequenceMethods

  该结构体持有指向对象用于实现序列协议的函数的指针。

lenfunc PySequenceMethods .sq_length

  The corresponding slot ID `Py_sq_length` is part of the 稳定 ABI.

  此函数被 `PySequence_Size()` 和 `PyObject_Size()` 所使用，并具有与它们相同的签名。 它还被用于通过 `sq_item` 和 `sq_ass_item` 槽位来处理负索引号。

binaryfunc PySequenceMethods .sq_concat

  The corresponding slot ID `Py_sq_concat` is part of the 稳定 ABI.

  此函数被 `PySequence_Concat()` 所使用并具有相同的签名。 在尝试通过 `nb_add` 槽位执行数值相加之后它还会被用于 `+` 运算符。

ssizeargfunc PySequenceMethods .sq_repeat

  The corresponding slot ID `Py_sq_repeat` is part of the 稳定 ABI.

  此函数被 `PySequence_Repeat()` 所使用并具有相同的签名。 在尝试通过 `nb_multiply` 槽位执行数值相乘之后它还会被用于 `*` 运算符。

ssizeargfunc PySequenceMethods .sq_item

  The corresponding slot ID `Py_sq_item` is part of the 稳定 ABI.

  此函数被 `PySequence_GetItem()` 所使用并具有相同的签名。 在尝试通过 `mp_subscript` 槽位执行下标操作之后它还会被用于 `PyObject_GetItem()`。 该槽位必须被填充以便 `PySequence_Check()` 函数返回 `1`，否则它可以为 `NULL`。

  负索引号是按如下方式处理的：如果 `sq_length` 槽位已被填充，它将被调用并使用序列长度来计算出正索引号并传给 `sq_item`。 如果 `sq_length` 为 `NULL`，索引号将原样传给此函数。

ssizeobjargproc PySequenceMethods .sq_ass_item

  The corresponding slot ID `Py_sq_ass_item` is part of the 稳定 ABI.

  此函数被 `PySequence_SetItem()` 所使用并具有相同的签名。 在尝试通过 `mp_ass_subscript` 槽位执行条目赋值和删除操作之后它还会被用于 `PyObject_SetItem()` 和 `PyObject_DelItem()`。 如果对象不支持条目和删除则该槽位可以保持为 `NULL`。

objobjproc PySequenceMethods .sq_contains

  The corresponding slot ID `Py_sq_contains` is part of the 稳定 ABI.

  该函数可供 `PySequence_Contains()` 使用并具有相同的签名。 此槽位可以保持为 `NULL`，在此情况下 `PySequence_Contains()` 只需遍历该序列直到找到一个匹配。

binaryfunc PySequenceMethods .sq_inplace_concat

  The corresponding slot ID `Py_sq_inplace_concat` is part of the 稳定 ABI.

  此函数被 `PySequence_InPlaceConcat()` 所使用并具有相同的签名。 它应当修改它的第一个操作数，并将其返回。 该槽位可以保持为 `NULL`，在此情况下 `PySequence_InPlaceConcat()` 将回退到 `PySequence_Concat()`。 在尝试通过 `nb_inplace_add` 槽位执行数字原地相加之后它还会被用于增强赋值运算符 `+=`。

ssizeargfunc PySequenceMethods .sq_inplace_repeat

  The corresponding slot ID `Py_sq_inplace_repeat` is part of the 稳定 ABI.

  此函数被 `PySequence_InPlaceRepeat()` 所使用并具有相同的签名。 它应当修改它的第一个操作数，并将其返回。 该槽位可以保持为 `NULL`，在此情况下 `PySequence_InPlaceRepeat()` 将回退到 `PySequence_Repeat()`。 在尝试通过 `nb_inplace_multiply` 槽位执行数字原地相乘之后它还会被用于增强赋值运算符 `*=`。

## 缓冲区对象结构体

type PyBufferProcs

  此结构体持有指向 缓冲区协议 所需要的函数的指针。 该协议定义了导出方对象要如何向消费方对象暴露其内部数据。

getbufferproc PyBufferProcs .bf_getbuffer

  The corresponding slot ID `Py_bf_getbuffer` is part of the 稳定 ABI 自 3.11 版起.

  此函数的签名为:

      int (PyObject *exporter, Py_buffer *view, int flags);

  处理发给 exporter 的请求来填充 flags 所指定的 view。 除第 (3) 点外，此函数的实现必须执行以下步骤：

  1. 检查请求是否能被满足。 如果不能，则会引发 `BufferError`，将 view->obj 设为 `NULL` 并返回 `-1`。

  2. 填充请求的字段。

  3. 递增用于保存导出次数的内部计数器。

  4. 将 view->obj 设为 exporter 并递增 view->obj。

  5. 返回 `0`。

  如果 exporter 是缓冲区提供方的链式或树型结构的一部分，则可以使用两种主要方案：

  - 重导出：树型结构的每个成员作为导出对象并将 view->obj 设为对其自身的新引用。

  - 重定向：缓冲区请求将被重定向到树型结构的根对象。 在此，view->obj 将为对根对象的新引用。

  view 中每个字段的描述参见 缓冲区结构体 一节，导出方对于特定请求应当如何反应参见 缓冲区请求类型 一节。

  所有在 `Py_buffer` 结构体中被指向的内存都属于导出方并必须保持有效直到不再有任何消费方。 `format`, `shape`, `strides`, `suboffsets` 和 `internal` 对于消费方来说是只读的。

  `PyBuffer_FillInfo()` 提供了一种暴露简单字节缓冲区同时正确处理地所有请求类型的简便方式。

  `PyObject_GetBuffer()` 是针对包装此函数的消费方的接口。

releasebufferproc PyBufferProcs .bf_releasebuffer

  The corresponding slot ID `Py_bf_releasebuffer` is part of the 稳定 ABI 自 3.11 版起.

  此函数的签名为:

      void (PyObject *exporter, Py_buffer *view);

  处理释放缓冲区资源的请求。 如果不需要释放任何资源，则 `PyBufferProcs.bf_releasebuffer` 可以为 `NULL`。 在其他情况下，此函数的标准实现将执行以下的可选步骤：

  1. 递减用于保存导出次数的内部计数器。

  2. 如果计数器为 `0`，则释放所有关联到 view 的内存。

  导出方必须使用 `internal` 字段来记录缓冲区专属的资源。 该字段将确保恒定，而消费方则可能将原始缓冲区作为 view 参数传入。

  此函数不可递减 view->obj，因为这是在 `PyBuffer_Release()` 中自动完成的（此方案适用于打破循环引用）。

  `PyBuffer_Release()` 是针对包装此函数的消费方的接口。

## 异步对象结构体

Added in version 3.5.

type PyAsyncMethods

  此结构体将持有指向需要用来实现 awaitable 和 asynchronous iterator 对象的函数的指针。

  结构体定义如下:

      typedef struct {
          unaryfunc am_await;
          unaryfunc am_aiter;
          unaryfunc am_anext;
          sendfunc am_send;
      } PyAsyncMethods;

unaryfunc PyAsyncMethods .am_await

  The corresponding slot ID `Py_am_await` is part of the 稳定 ABI 自 3.5 版起.

  此函数的签名为:

      PyObject *am_await(PyObject *self);

  返回的对象必须为 iterator，即对其执行 `PyIter_Check()` 必须返回 `1`。

  如果一个对象不是 awaitable 则此槽位可被设为 `NULL`。

unaryfunc PyAsyncMethods .am_aiter

  The corresponding slot ID `Py_am_aiter` is part of the 稳定 ABI 自 3.5 版起.

  此函数的签名为:

      PyObject *am_aiter(PyObject *self);

  必须返回一个 asynchronous iterator 对象。 请参阅 `__anext__()` 了解详情。

  如果一个对象没有实现异步迭代协议则此槽位可被设为 `NULL`。

unaryfunc PyAsyncMethods .am_anext

  The corresponding slot ID `Py_am_anext` is part of the 稳定 ABI 自 3.5 版起.

  此函数的签名为:

      PyObject *am_anext(PyObject *self);

  必须返回一个 awaitable 对象。 请参阅 `__anext__()` 了解详情。 此槽位可被设为 `NULL`。

sendfunc PyAsyncMethods .am_send

  The corresponding slot ID `Py_am_send` is part of the 稳定 ABI 自 3.10 版起.

  此函数的签名为:

      PySendResult am_send(PyObject *self, PyObject *arg, PyObject **result);

  请参阅 `PyIter_Send()` 了解详情。 此槽位可被设为 `NULL`。

  Added in version 3.10.

## 槽位类型 typedef

typedef PyObject *(*allocfunc)( PyTypeObject *cls, Py_ssize_t nitems)
  属于 稳定 ABI.

  此函数的设计目标是将内存分配与内存初始化进行分离。 它应当返回一个指向足够容纳实例长度，适当对齐，并初始化为零的内存块的指针，但将 `ob_refcnt` 设为 `1` 并将 `ob_type` 设为 type 参数。 如果类型的 `tp_itemsize` 为非零值，则对象的 `ob_size` 字段应当被初始化为 nitems 而分配内存块的长度应为 `tp_basicsize + nitems*tp_itemsize`，并舍入到 `sizeof(void*)` 的倍数；在其他情况下，nitems 将不会被使用而内存块的长度应为 `tp_basicsize`。

  此函数不应执行任何其他实例初始化操作，即使是分配额外内存也不应执行；那应当由 `tp_new` 来完成。

typedef void (*destructor)( PyObject *)
  属于 稳定 ABI.

typedef void (*freefunc)(void*)

  参见 `tp_free`。

typedef PyObject *(*newfunc)( PyTypeObject *, PyObject *, PyObject *)
  属于 稳定 ABI.

  参见 `tp_new`。

typedef int (*initproc)( PyObject *, PyObject *, PyObject *)
  属于 稳定 ABI.

  参见 `tp_init`。

typedef PyObject *(*reprfunc)( PyObject *)
  属于 稳定 ABI.

  参见 `tp_repr`。

typedef PyObject *(*getattrfunc)( PyObject *self, char *attr)
  属于 稳定 ABI.

  返回对象的指定属性的值。

typedef int (*setattrfunc)( PyObject *self, char *attr, PyObject *value)
  属于 稳定 ABI.

  为对象设置指定属性的值。 将 value 参数设为 `NULL` 将删除该属性。

typedef PyObject *(*getattrofunc)( PyObject *self, PyObject *attr)
  属于 稳定 ABI.

  返回对象的指定属性的值。

  参见 `tp_getattro`。

typedef int (*setattrofunc)( PyObject *self, PyObject *attr, PyObject *value)
  属于 稳定 ABI.

  为对象设置指定属性的值。 将 value 参数设为 `NULL` 将删除该属性。

  参见 `tp_setattro`。

typedef PyObject *(*descrgetfunc)( PyObject *, PyObject *, PyObject *)
  属于 稳定 ABI.

  参见 `tp_descr_get`。

typedef int (*descrsetfunc)( PyObject *, PyObject *, PyObject *)
  属于 稳定 ABI.

  参见 `tp_descr_set`。

typedef Py_hash_t (*hashfunc)( PyObject *)
  属于 稳定 ABI.

  参见 `tp_hash`。

typedef PyObject *(*richcmpfunc)( PyObject *, PyObject *, int)
  属于 稳定 ABI.

  参见 `tp_richcompare`。

typedef PyObject *(*getiterfunc)( PyObject *)
  属于 稳定 ABI.

  参见 `tp_iter`。

typedef PyObject *(*iternextfunc)( PyObject *)
  属于 稳定 ABI.

  参见 `tp_iternext`。

typedef Py_ssize_t (*lenfunc)( PyObject *)
  属于 稳定 ABI.

typedef int (*getbufferproc)( PyObject *, Py_buffer *, int)
  属于 稳定 ABI 自 3.12 版起.

typedef void (*releasebufferproc)( PyObject *, Py_buffer *)
  属于 稳定 ABI 自 3.12 版起.

typedef PyObject *(*unaryfunc)( PyObject *)
  属于 稳定 ABI.

typedef PyObject *(*binaryfunc)( PyObject *, PyObject *)
  属于 稳定 ABI.

typedef PySendResult (*sendfunc)( PyObject *, PyObject *, PyObject **)

  参见 `am_send`。

typedef PyObject *(*ternaryfunc)( PyObject *, PyObject *, PyObject *)
  属于 稳定 ABI.

typedef PyObject *(*ssizeargfunc)( PyObject *, Py_ssize_t )
  属于 稳定 ABI.

typedef int (*ssizeobjargproc)( PyObject *, Py_ssize_t , PyObject *)
  属于 稳定 ABI.

typedef int (*objobjproc)( PyObject *, PyObject *)
  属于 稳定 ABI.

typedef int (*objobjargproc)( PyObject *, PyObject *, PyObject *)
  属于 稳定 ABI.

## 例子

下面是一些 Python 类型定义的简单示例。 其中包括你可能会遇到的通常用法。 有些演示了令人困惑的边际情况。 要获取更多示例、实践信息以及教程，请参阅 自定义扩展类型：教程 和 定义扩展类型：已分类主题。

一个基本的 静态类型:

    typedef struct {
        PyObject_HEAD
        const char *data;
    } MyObject;

    static PyTypeObject MyObject_Type = {
        PyVarObject_HEAD_INIT(NULL, 0)
        .tp_name = "mymod.MyObject",
        .tp_basicsize = sizeof(MyObject),
        .tp_doc = PyDoc_STR("My objects"),
        .tp_new = myobj_new,
        .tp_dealloc = (destructor)myobj_dealloc,
        .tp_repr = (reprfunc)myobj_repr,
    };

你可能还会看到带有更繁琐的初始化器的较旧代码（特别是在 CPython 代码库中）:

    static PyTypeObject MyObject_Type = {
        PyVarObject_HEAD_INIT(NULL, 0)
        "mymod.MyObject",               /* tp_name */
        sizeof(MyObject),               /* tp_basicsize */
        0,                              /* tp_itemsize */
        (destructor)myobj_dealloc,      /* tp_dealloc */
        0,                              /* tp_vectorcall_offset */
        0,                              /* tp_getattr */
        0,                              /* tp_setattr */
        0,                              /* tp_as_async */
        (reprfunc)myobj_repr,           /* tp_repr */
        0,                              /* tp_as_number */
        0,                              /* tp_as_sequence */
        0,                              /* tp_as_mapping */
        0,                              /* tp_hash */
        0,                              /* tp_call */
        0,                              /* tp_str */
        0,                              /* tp_getattro */
        0,                              /* tp_setattro */
        0,                              /* tp_as_buffer */
        0,                              /* tp_flags */
        PyDoc_STR("My objects"),        /* tp_doc */
        0,                              /* tp_traverse */
        0,                              /* tp_clear */
        0,                              /* tp_richcompare */
        0,                              /* tp_weaklistoffset */
        0,                              /* tp_iter */
        0,                              /* tp_iternext */
        0,                              /* tp_methods */
        0,                              /* tp_members */
        0,                              /* tp_getset */
        0,                              /* tp_base */
        0,                              /* tp_dict */
        0,                              /* tp_descr_get */
        0,                              /* tp_descr_set */
        0,                              /* tp_dictoffset */
        0,                              /* tp_init */
        0,                              /* tp_alloc */
        myobj_new,                      /* tp_new */
    };

一个支持弱引用、实例字典和哈希运算的类型:

    typedef struct {
        PyObject_HEAD
        const char *data;
    } MyObject;

    static PyTypeObject MyObject_Type = {
        PyVarObject_HEAD_INIT(NULL, 0)
        .tp_name = "mymod.MyObject",
        .tp_basicsize = sizeof(MyObject),
        .tp_doc = PyDoc_STR("My objects"),
        .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
             Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_MANAGED_DICT |
             Py_TPFLAGS_MANAGED_WEAKREF,
        .tp_new = myobj_new,
        .tp_traverse = (traverseproc)myobj_traverse,
        .tp_clear = (inquiry)myobj_clear,
        .tp_alloc = PyType_GenericNew,
        .tp_dealloc = (destructor)myobj_dealloc,
        .tp_repr = (reprfunc)myobj_repr,
        .tp_hash = (hashfunc)myobj_hash,
        .tp_richcompare = PyBaseObject_Type.tp_richcompare,
    };

一个不能被子类化且不能被调用以使用 `Py_TPFLAGS_DISALLOW_INSTANTIATION` 旗标创建实例（例如使用单独的工厂函数）的 str 子类:

    typedef struct {
        PyUnicodeObject raw;
        char *extra;
    } MyStr;

    static PyTypeObject MyStr_Type = {
        PyVarObject_HEAD_INIT(NULL, 0)
        .tp_name = "mymod.MyStr",
        .tp_basicsize = sizeof(MyStr),
        .tp_base = NULL,  // set to &PyUnicode_Type in module init
        .tp_doc = PyDoc_STR("my custom str"),
        .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
        .tp_repr = (reprfunc)myobj_repr,
    };

最简单的固定长度实例 静态类型:

    typedef struct {
        PyObject_HEAD
    } MyObject;

    static PyTypeObject MyObject_Type = {
        PyVarObject_HEAD_INIT(NULL, 0)
        .tp_name = "mymod.MyObject",
    };

最简单的具有可变长度实例的 静态类型:

    typedef struct {
        PyObject_VAR_HEAD
        const char *data[1];
    } MyObject;

    static PyTypeObject MyObject_Type = {
        PyVarObject_HEAD_INIT(NULL, 0)
        .tp_name = "mymod.MyObject",
        .tp_basicsize = sizeof(MyObject) - sizeof(char *),
        .tp_itemsize = sizeof(char *),
    };