类型对象

  • type PyTypeObject
  • 属于 受限 API (作为不透明的结构体). 对象的 C 结构用于描述 builtin 类型。
  • 属于 稳定 ABI. 这是属于 type 对象的 type object,它在 Python 层面和 type 是相同的对象。
  • 如果对象 o 是一个类型对象,包括派生自标准类型对象的类型实例则返回非零值。 在所有其它情况下都返回 0。 此函数将总是成功执行。
  • 如果对象 o 是一个类型对象,但不是标准类型对象的子类型则返回非零值。 在所有其它情况下都返回 0。 此函数将总是成功执行。
  • unsigned int PyType_ClearCache()
  • 属于 稳定 ABI. 清空内部查找缓存。 返回当前版本标签。
  • 属于 稳定 ABI. 返回 type 的 tp_flags 成员。 此函数主要是配合 Py_LIMITED_API 使用;单独的旗标位会确保在各个 Python 发布版之间保持稳定,但对 tp_flags 本身的访问并不是 受限 API 的一部分。

Added in version 3.2.

在 3.4 版本发生变更: 返回类型现在是 unsigned long 而不是 long

  • 返回类型对象的内部命名空间,它在其他情况下只能通过只读代理 (cls.__dict__) 对外公开。 这可以代替直接访问 tp_dict。 返回的字典必须视为是只读的。

该函数用于特定的嵌入和语言绑定场景,在这些场景下需要直接访问该字典而间接访问(例如通过代理或 PyObject_GetAttr() 访问)并不足够。

扩展模块在设置它们自己的类型时应当继续直接或间接地使用 tp_dict

Added in version 3.12.

  • 属于 稳定 ABI. 使该类型及其所有子类型的内部查找缓存失效。 此函数必须在对该类型的属性或基类进行任何手动修改之后调用。
  • 注册 callback 作为类型监视器。 返回一个非负的整数 ID,它必须传给将来对 PyType_Watch() 的调用。 如果出错(例如没有足够的可用监视器 ID),则返回 -1 并设置一个异常。

Added in version 3.12.

  • int PyType_ClearWatcher(int watcher_id)
  • 清除由 watcher_id (之前从 PyType_AddWatcher() 返回) 所标识的 watcher。 成功时返回 0,出错时(例如 watcher_id 未被注册)返回 -1

扩展在调用 PyType_ClearWatcher 时绝不能使用不是之前调用 PyType_AddWatcher() 所返回的 watcher_id。

Added in version 3.12.

  • int PyType_Watch(int watcher_id, PyObject *type)
  • 将 type 标记为已监视。 每当 PyType_Modified() 报告 type 发生变化时 PyType_AddWatcher() 赋予 watcher_id 的回调将被调用。 (如果在 type 的一系列连续修改之间没有调用 PyTypeLookup(),则回调只能被调用一次;这是一个实现细节并可能发生变化)。

扩展在调用 PyType_Watch 时绝不能使用不是之前调用 PyType_AddWatcher() 所返回的 watcher_id。

Added in version 3.12.

  • typedef int (PyType_WatchCallback)(PyObject type)
  • 类型监视器回调函数的类型。

回调不可以修改 type 或是导致 PyType_Modified() 在 type 或其 MRO 中的任何类型上被调用;违反此规则可能导致无限递归。

Added in version 3.12.

  • 如果类型对象 o 设置了特性 feature 则返回非零值。 类型特性是用单个比特位旗标来表示的。
  • 如果类型对象包括了对循环检测器的支持则返回真值;这将测试类型旗标 Py_TPFLAGS_HAVE_GC
  • 属于 稳定 ABI. 如果 a 是 b 的子类型则返回真值。

此函数只检查实际的子类型,这意味着 __subclasscheck__() 不会在 b 上被调用。 请调用 PyObject_IsSubclass() 来执行与 issubclass() 所做的相同检查。

  • 返回值:新的引用。 属于 稳定 ABI. 类型对象的 tp_alloc 槽位的通用处理器。 请使用 Python 的默认内存分配机制来分配一个新的实例并将其所有内容初始化为 NULL
  • 返回值:新的引用。 属于 稳定 ABI. 类型对象的 tp_new 槽位的通用处理器。 请使用类型的 tp_alloc 槽位来创建一个新的实例。
  • 属于 稳定 ABI. 最终化一个类型对象。 这应当在所有类型对象上调用以完成它们的初始化。 此函数会负责从一个类型的基类添加被继承的槽位。 成功时返回 0,或是在出错时返回 -1 并设置一个异常。

备注

如果某些基类实现了 GC 协议并且所提供的类型的旗标中未包括 Py_TPFLAGS_HAVE_GC,则将自动从其父类实现 GC 协议。 相反地,如果被创建的类型的旗标中确实包含 Py_TPFLAGS_HAVE_GC 则它 必须 自己实现 GC 协议,至少要实现 tp_traverse 句柄。

  • 返回值:新的引用。 属于 稳定 ABI 自 3.11 版起. 返回类型名称。 等同于获取类型的 __name__ 属性。

Added in version 3.11.

  • 返回值:新的引用。 属于 稳定 ABI 自 3.11 版起. 返回类型的限定名称。 等同于获取类型的 __qualname__ 属性。

Added in version 3.11.

  • 属于 稳定 ABI 自 3.13 版起. 返回类型的完整限定名称。 等同于 f"{type.__module__}.{type.__qualname__}",或者如果 type.__module__ 不是字符串或是等于 "builtins" 则等同于 type.__qualname__

Added in version 3.13.

Added in version 3.13.

  • 属于 稳定 ABI 自 3.4 版起. 返回存储在给定槽位中的函数指针。 如果结果为 NULL,则表示或者该槽位为 NULL,或者该函数调用传入了无效的形参。 调用方通常要将结果指针转换到适当的函数类型。

请参阅 PyType_Slot.slot 查看可用的 slot 参数值。

Added in version 3.4.

在 3.10 版本发生变更: PyType_GetSlot() 现在可以接受所有类型。 在此之前,它被限制为 堆类型

如果没有关联到给定类型的模块,则设置 TypeError 并返回 NULL

此函数通常被用于获取方法定义所在的模块。 请注意在这样的方法中,PyType_GetModule(Py_TYPE(self)) 可能不会返回预期的结果。 Py_TYPE(self) 可以是目标类的一个 子类,而子类并不一定是在与其超类相同的模块中定义的。 请参阅 PyCMethod 了解如何获取方法定义所在的类。 请参阅 PyType_GetModuleByDef() 了解有关无法使用 PyCMethod 的情况。

Added in version 3.9.

如果没有关联到给定类型的模块,则设置 TypeError 并返回 NULL

如果 type 有关联的模块但其状态为 NULL,则返回 NULL 且不设置异常。

Added in version 3.9.

  • 属于 稳定 ABI 自 3.13 版起. 找到所属模块基于给定的 PyModuleDef def 创建的第一个上级类,并返回该模块。

如果未找到模块,则会引发 TypeError 并返回 NULL

此函数预期会与 PyModule_GetState() 一起使用以便从槽位方法 (如 tp_initnb_add) 及其他定义方法的类无法使用 PyCMethod 调用惯例来传递的场合获取模块状态。

Added in version 3.11.

  • 这是 不稳定 API。它可在次发布版中不经警告地改变。

尝试为给定的类型设置一个版本标签。

如果类型已有合法的版本标签或已设置了新的版本标签则返回 1,或者如果无法设置新的标签则返回 0。

Added in version 3.12.

创建堆分配类型

下列函数和结构体可被用来创建 堆类型

元类 metaclass 用于构建结果类型对象。 当 metaclass 为 NULL 时,元类将派生自 bases (或者如果 bases 为 NULL 则派生自 Py_tp_base[s] 槽位,见下文)。

不支持重写 tp_new 的元类,除非 tp_newNULL。 (为了向下兼容,其他 PyType_From* 函数允许这样的元类。 它们将忽略 tp_new,可能导致不完整的初始化。 这样的元类已被弃用并在 Python 3.14+ 中停止支持。)

bases 参数可被用来指定基类;它可以是单个类或由多个类组成的元组。 如果 bases 为 NULL,则会改用 Py_tp_bases 槽位。 如果该槽位也为 NULL,则会改用 Py_tp_base 槽位。 如果该槽位同样为 NULL,则新类型将派生自 object

module 参数可被用来记录新类定义所在的模块。 它必须是一个模块对象或为 NULL。 如果不为 NULL,则该模块会被关联到新类型并且可在之后通过 PyType_GetModule() 来获取。 这个关联模块不可被子类继承;它必须为每个类单独指定。

此函数会在新类型上调用 PyType_Ready()

请注意此函数 不能 完全匹配调用 type() 或使用 class 语句的行为。 对于用户提供的类型或元类,推荐 调用 type (或元类) 而不是 PyType_From* 函数。 特别地:

Added in version 3.12.

  • 返回值:新的引用。 属于 稳定 ABI 自 3.10 版起. 等价于 PyType_FromMetaclass(NULL, module, spec, bases)

Added in version 3.9.

在 3.10 版本发生变更: 此函数现在接受一个单独类作为 bases 参数并接受 NULL 作为 tp_doc 槽位。

在 3.12 版本发生变更: 该函数现在可以找到并使用与所提供的基类相对应的元类。 在此之前,只会返回 type 实例。

元类的 tp_new 将被 忽略。 这可能导致不完整的初始化。 创建元类重写 tp_new 的类的做法已被弃用并且在 Python 3.14+ 中将不再被允许。

  • 返回值:新的引用。 属于 稳定 ABI 自 3.3 版起. 等价于 PyType_FromMetaclass(NULL, NULL, spec, bases)

Added in version 3.3.

在 3.12 版本发生变更: 该函数现在可以找到并使用与所提供的基类相对应的元类。 在此之前,只会返回 type 实例。

元类的 tp_new 将被 忽略。 这可能导致不完整的初始化。 创建元类重写 tp_new 的类的做法已被弃用并且在 Python 3.14+ 中将不再被允许。

  • 返回值:新的引用。 属于 稳定 ABI. 等价于 PyType_FromMetaclass(NULL, NULL, spec, NULL)

在 3.12 版本发生变更: 该函数现在可以找到并使用与 Py_tp_base[s] 槽位中提供的基类相对应的元类。 在此之前,只会返回 type 实例。

元类的 tp_new 将被 忽略。 这可能导致不完整的初始化。 创建元类重写 tp_new 的类的做法已被弃用并且在 Python 3.14+ 中将不再被允许。

  • type PyType_Spec
  • 属于 稳定 ABI (包括所有成员). 定义一个类型的行为的结构体。

    • const char *name

如果为零,则指定应当继承 tp_basicsize

如果为负数,则以其绝对值指定该类的实例在超类的 基础之上 还需要多少空间。 使用 PyObject_GetTypeData() 来获取通过此方式保留的子类专属内存的指针。

在 3.12 版本发生变更: 在之前版本中,此字段不能为负数。

  • int itemsize
  • 可变大小类型中一个元素的大小,以字节为单位。 用于设置 PyTypeObject.tp_itemsize。 注意事项请参阅 tp_itemsize 文档。

如果为零,则会继承 tp_itemsize。 扩展任意可变大小的类是很危险的,因为某些类型使用固定偏移量来标识可变大小的内存,这样就会与子类使用的固定大小的内存相重叠。 为了防止出错,只有在以下情况下才可以继承 itemsize:

  1. -

基类不是可变大小的 (即其 tp_itemsize)。

  1. -

所请求的 PyType_Spec.basicsize 为正值,表明基类的内存布局是已知的。

  1. -

所请求的 PyType_Spec.basicsize 为零,表明子类不会直接访问实例的内存。

  1. -

具有 Py_TPFLAGS_ITEMS_AT_END 旗标。

  • unsigned int flags

如果未设置 Py_TPFLAGS_HEAPTYPE 旗标,则 PyType_FromSpecWithBases() 会自动设置它。

  • PyType_Slot 结构体的数组。 以特殊槽位值 {0, NULL} 来结束。

每个槽位 ID 应当只被指定一次。

  • type PyType_Slot
  • 属于 稳定 ABI (包括所有成员). 定义一个类型的可选功能的结构体,包含一个槽位 ID 和一个值指针。

    • int slot
  • 槽位 ID。

槽位 ID 的类名像是结构体 PyTypeObject, PyNumberMethods, PySequenceMethods, PyMappingMethodsPyAsyncMethods 的字段名附加一个 Py_ 前缀。 举例来说,使用:

  1. -

Py_tp_dealloc 设置 PyTypeObject.tp_dealloc

  1. -

Py_nb_add 设置 PyNumberMethods.nb_add

  1. -

Py_sq_length 设置 PySequenceMethods.sq_length

下列 “offset” 字段不可使用 PyType_Slot 来设置:

  1. -

tp_weaklistoffset (如果可能请改用 Py_TPFLAGS_MANAGED_WEAKREF)

  1. -

tp_dictoffset (如果可能请改用 Py_TPFLAGS_MANAGED_DICT)

  1. -

tp_vectorcall_offset (请使用 PyMemberDef 中的 "__vectorcalloffset__")

如果无法转为 MANAGED 旗标 (例如,对于 vectorcall 或是为了支持早于 Python 3.12 的版本),请在 Py_tp_members 中指定 offset。 详情参见 PyMemberDef documentation

以下字段在创建堆类型时完全不可设置:

  1. -

tp_vectorcall (请使用 tp_new 和/或 tp_init)

  1. -

内部字段: tp_dict, tp_mro, tp_cache, tp_subclassestp_weaklist

在某些平台上设置 Py_tp_basesPy_tp_base 可能会有问题。 为了避免问题,请改用 PyType_FromSpecWithBases() 的 bases 参数。

在 3.9 版本发生变更: PyBufferProcs 中的槽位可能会在不受限 API 中被设置。

在 3.11 版本发生变更: 现在 bf_getbufferbf_releasebuffer 将在 受限 API 中可用。

  • void *pfunc
  • 该槽位的预期值。 在大多数情况下,这将是一个指向函数的指针。

Py_tp_doc 以外的槽位均不可为 NULL