常用对象结构

Python 中定义对象类型时会用到大量的结构体。本节将描述这些结构体以及它们是如何使用的。

基本对象类型和宏

所有 Python 对象最终在内存中的对象表示的开头共享少量字段。这些字段由 PyObjectPyVarObject 类型表示,这些类型又由一些宏的扩展定义,这些宏直接或间接地用于定义所有其他 Python 对象。其他宏可以在 引用计数 下找到。

type PyObject
属于 有限 API 的一部分。(只有部分成员是稳定的 ABI 的一部分。)

所有对象类型都是此类型的扩展。这是一种包含 Python 将对象指针视为对象所需信息的类型。在正常的 “release” 版本中,它仅包含对象的引用计数和指向相应类型对象的指针。实际上没有声明为 PyObject,但每个指向 Python 对象的指针都可以转换为 PyObject*。对成员的访问必须使用宏 Py_REFCNTPy_TYPE 完成。

type PyVarObject
属于 有限 API 的一部分。(只有部分成员是稳定的 ABI 的一部分。)

这是 PyObject 的扩展,添加了 ob_size 字段。这仅用于具有某种长度概念的对象。此类型在 Python/C API 中不常出现。对成员的访问必须使用宏 Py_REFCNTPy_TYPEPy_SIZE 完成。

PyObject_HEAD

这是一个在声明表示没有可变长度的对象的的新类型时使用的宏。PyObject_HEAD 宏展开为

PyObject ob_base;

参见上面 PyObject 的文档。

PyObject_VAR_HEAD

这是一个在声明表示长度因实例而异的对象的的新类型时使用的宏。PyObject_VAR_HEAD 宏展开为

PyVarObject ob_base;

参见上面 PyVarObject 的文档。

int Py_Is(PyObject *x, PyObject *y)
自 3.10 版本起,属于 稳定 ABI 的一部分。

测试 x 对象是否为 y 对象,与 Python 中的 x is y 相同。

3.10 版本中新增。

int Py_IsNone(PyObject *x)
自 3.10 版本起,属于 稳定 ABI 的一部分。

测试对象是否为 None 单例,与 Python 中的 x is None 相同。

3.10 版本中新增。

int Py_IsTrue(PyObject *x)
自 3.10 版本起,属于 稳定 ABI 的一部分。

测试对象是否为 True 单例,与 Python 中的 x is True 相同。

3.10 版本中新增。

int Py_IsFalse(PyObject *x)
自 3.10 版本起,属于 稳定 ABI 的一部分。

测试对象是否为 False 单例,与 Python 中的 x is False 相同。

3.10 版本中新增。

PyTypeObject *Py_TYPE(PyObject *o)
返回值:借用引用。

获取 Python 对象 o 的类型。

返回一个 借用引用

使用 Py_SET_TYPE() 函数设置对象类型。

在 3.11 版本中变更: Py_TYPE() 已更改为内联静态函数。参数类型不再是 const PyObject*

int Py_IS_TYPE(PyObject *o, PyTypeObject *type)

如果对象 o 的类型为 type,则返回非零值。否则返回零。等同于:Py_TYPE(o) == type

3.9 版本中新增。

void Py_SET_TYPE(PyObject *o, PyTypeObject *type)

将对象 o 的类型设置为 type

3.9 版本中新增。

Py_ssize_t Py_SIZE(PyVarObject *o)

获取 Python 对象 o 的大小。

使用 Py_SET_SIZE() 函数设置对象大小。

在 3.11 版本中变更: Py_SIZE() 已更改为内联静态函数。参数类型不再是 const PyVarObject*

void Py_SET_SIZE(PyVarObject *o, Py_ssize_t size)

将对象 o 的大小设置为 size

3.9 版本中新增。

PyObject_HEAD_INIT(type)

这是一个宏,它展开为新的 PyObject 类型的初始化值。此宏展开为

_PyObject_EXTRA_INIT
1, type,
PyVarObject_HEAD_INIT(type, size)

这是一个宏,它展开为新的 PyVarObject 类型的初始化值,包括 ob_size 字段。此宏展开为

_PyObject_EXTRA_INIT
1, type, size,

实现函数和方法

type PyCFunction
属于 稳定 ABI 的一部分。

用于在 C 中实现大多数 Python 可调用对象的函数的类型。此类型的函数接受两个 PyObject* 参数并返回一个这样的值。如果返回值为 NULL,则应已设置异常。如果不是 NULL,则返回值被解释为 Python 中公开的函数的返回值。该函数必须返回一个新的引用。

函数签名是

PyObject *PyCFunction(PyObject *self,
                      PyObject *args);
type PyCFunctionWithKeywords
属于 稳定 ABI 的一部分。

用于在 C 中实现具有签名 METH_VARARGS | METH_KEYWORDS 的 Python 可调用对象的函数的类型。函数签名是

PyObject *PyCFunctionWithKeywords(PyObject *self,
                                  PyObject *args,
                                  PyObject *kwargs);
type PyCFunctionFast
自 3.13 版本以来,属于 稳定 ABI 的一部分。

用于在 C 中实现具有签名 METH_FASTCALL 的 Python 可调用对象的函数的类型。函数签名是

PyObject *PyCFunctionFast(PyObject *self,
                          PyObject *const *args,
                          Py_ssize_t nargs);
type PyCFunctionFastWithKeywords
自 3.13 版本以来,属于 稳定 ABI 的一部分。

用于在 C 中实现具有签名 METH_FASTCALL | METH_KEYWORDS 的 Python 可调用对象的函数的类型。函数签名是

PyObject *PyCFunctionFastWithKeywords(PyObject *self,
                                      PyObject *const *args,
                                      Py_ssize_t nargs,
                                      PyObject *kwnames);
type PyCMethod

用于在 C 中实现具有签名 METH_METHOD | METH_FASTCALL | METH_KEYWORDS 的 Python 可调用对象的函数的类型。函数签名是

PyObject *PyCMethod(PyObject *self,
                    PyTypeObject *defining_class,
                    PyObject *const *args,
                    Py_ssize_t nargs,
                    PyObject *kwnames)

3.9 版本中新增。

type PyMethodDef
属于 稳定 ABI 的一部分(包括所有成员)。

用于描述扩展类型的方法的结构。此结构具有四个字段

const char *ml_name

方法名称。

PyCFunction ml_meth

指向 C 实现的指针。

int ml_flags

指示应如何构造调用的标志位。

const char *ml_doc

指向文档字符串的内容。

ml_meth 是一个 C 函数指针。这些函数可以是不同的类型,但它们始终返回 PyObject*。如果该函数不是 PyCFunction 类型,则编译器将需要在方法表中进行强制转换。即使 PyCFunction 将第一个参数定义为 PyObject*,方法实现通常使用 self 对象的特定 C 类型。

ml_flags 字段是一个位字段,可以包括以下标志。各个标志指示调用约定或绑定约定。

存在以下调用约定

METH_VARARGS

这是典型的调用约定,其中方法具有 PyCFunction 类型。该函数期望两个 PyObject* 值。第一个是方法的 self 对象;对于模块函数,它是模块对象。第二个参数(通常称为 args)是一个表示所有参数的元组对象。通常使用 PyArg_ParseTuple()PyArg_UnpackTuple() 来处理此参数。

METH_KEYWORDS

只能与其他标志的某些组合一起使用:METH_VARARGS | METH_KEYWORDSMETH_FASTCALL | METH_KEYWORDSMETH_METHOD | METH_FASTCALL | METH_KEYWORDS

METH_VARARGS | METH_KEYWORDS

具有这些标志的方法必须是 PyCFunctionWithKeywords 类型。该函数期望三个参数:selfargskwargs,其中 kwargs 是所有关键字参数的字典,如果没有任何关键字参数,则可能为 NULL。通常使用 PyArg_ParseTupleAndKeywords() 来处理这些参数。

METH_FASTCALL

仅支持位置参数的快速调用约定。这些方法具有 PyCFunctionFast 类型。第一个参数是 self,第二个参数是一个 C 的 PyObject* 值数组,表示参数,第三个参数是参数的数量(数组的长度)。

在 3.7 版本中添加。

在 3.10 版本中更改: METH_FASTCALL 现在是 稳定 ABI 的一部分。

METH_FASTCALL | METH_KEYWORDS

支持关键字参数的 METH_FASTCALL 扩展,其方法的类型为 PyCFunctionFastWithKeywords。关键字参数的传递方式与 vectorcall 协议 中的方式相同:有一个额外的第四个 PyObject* 参数,它是一个表示关键字参数名称(保证是字符串)的元组,如果没有关键字,则可能为 NULL。关键字参数的值存储在 args 数组中,位于位置参数之后。

在 3.7 版本中添加。

METH_METHOD

只能与其他标志组合使用:METH_METHOD | METH_FASTCALL | METH_KEYWORDS

METH_METHOD | METH_FASTCALL | METH_KEYWORDS

扩展 METH_FASTCALL | METH_KEYWORDS,支持定义类,即包含相关方法的类。定义类可能是 Py_TYPE(self) 的超类。

该方法需要是 PyCMethod 类型,与 METH_FASTCALL | METH_KEYWORDS 相同,但 在 self 之后添加了 defining_class 参数。

3.9 版本中新增。

METH_NOARGS

如果使用 METH_NOARGS 标志列出,则无参数的方法不需要检查是否提供了参数。它们需要是 PyCFunction 类型。第一个参数通常命名为 self,并将保存对模块或对象实例的引用。在所有情况下,第二个参数将为 NULL

该函数必须有 2 个参数。由于第二个参数未使用,可以使用 Py_UNUSED 来防止编译器警告。

METH_O

带有单个对象参数的方法可以使用 METH_O 标志列出,而不是使用 "O" 参数调用 PyArg_ParseTuple()。它们的类型为 PyCFunction,带有 self 参数,以及一个 PyObject* 参数,表示单个参数。

这两个常量不用于指示调用约定,而是与类方法一起使用时的绑定。它们不能用于为模块定义的函数。对于任何给定的方法,最多可以设置这些标志中的一个。

METH_CLASS

该方法将传递类型对象作为第一个参数,而不是该类型的实例。这用于创建类方法,类似于使用 classmethod() 内置函数创建的方法。

METH_STATIC

该方法将传递 NULL 作为第一个参数,而不是该类型的实例。这用于创建静态方法,类似于使用 staticmethod() 内置函数创建的方法。

另一个常量控制是否加载方法来代替具有相同方法名称的另一个定义。

METH_COEXIST

该方法将加载以代替现有定义。如果没有 METH_COEXIST,默认是跳过重复定义。由于槽包装器在方法表之前加载,例如,存在 sq_contains 槽将生成一个名为 __contains__() 的包装方法,并阻止加载具有相同名称的相应 PyCFunction。定义该标志后,PyCFunction 将加载以代替包装对象,并将与该槽共存。这很有帮助,因为对 PyCFunction 的调用比包装对象调用更优化。

PyObject *PyCMethod_New(PyMethodDef *ml, PyObject *self, PyObject *module, PyTypeObject *cls)
返回值:新引用。 自 3.9 版本以来,是 稳定 ABI 的一部分。

ml 转换为 Python 可调用 对象。调用者必须确保 ml 的生存时间长于 可调用 对象。通常,ml 被定义为静态变量。

调用时,self 参数将作为 self 参数传递给 ml->ml_meth 中的 C 函数。self 可以是 NULL

可以使用给定的 module 参数设置 可调用 对象的 __module__ 属性。module 应该是一个 Python 字符串,它将用作定义该函数的模块的名称。如果不可用,可以将其设置为 NoneNULL

另请参阅

function.__module__

cls 参数将作为 defining_class 参数传递给 C 函数。如果 ml->ml_flags 上设置了 METH_METHOD,则必须设置此参数。

3.9 版本中新增。

PyObject *PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)
返回值:新引用。稳定 ABI 的一部分。

等效于 PyCMethod_New(ml, self, module, NULL)

PyObject *PyCFunction_New(PyMethodDef *ml, PyObject *self)
返回值:新引用。 自 3.4 版本以来,是 稳定 ABI 的一部分。

等效于 PyCMethod_New(ml, self, NULL, NULL)

访问扩展类型的属性

type PyMemberDef
属于 稳定 ABI 的一部分(包括所有成员)。

描述类型属性的结构,该属性对应于 C 结构成员。在定义类时,将这些结构的以 NULL 结尾的数组放入 tp_members 槽中。

其字段依次为

const char *name

成员的名称。NULL 值标记 PyMemberDef[] 数组的末尾。

该字符串应该是静态的,不会对其进行复制。

int type

C 结构体中成员的类型。有关可能的值,请参阅成员类型

Py_ssize_t offset

成员在类型对象的结构体中所处的字节偏移量。

int flags

成员标志中的零个或多个标志,使用按位或组合。

const char *doc

文档字符串,或 NULL。该字符串应该是静态的,不会对其进行复制。通常,它使用 PyDoc_STR 定义。

默认情况下(当flags0 时),成员允许读写访问。对于只读访问,请使用 Py_READONLY 标志。某些类型,如 Py_T_STRING,表示 Py_READONLY。只有 Py_T_OBJECT_EX (和旧式的 T_OBJECT)成员可以被删除。

对于堆分配的类型(使用 PyType_FromSpec() 或类似方法创建),PyMemberDef 可能包含特殊成员 "__vectorcalloffset__" 的定义,它对应于类型对象中的 tp_vectorcall_offset。这些必须使用 Py_T_PYSSIZETPy_READONLY 定义,例如

static PyMemberDef spam_type_members[] = {
    {"__vectorcalloffset__", Py_T_PYSSIZET,
     offsetof(Spam_object, vectorcall), Py_READONLY},
    {NULL}  /* Sentinel */
};

(你可能需要 #include <stddef.h> 来使用 offsetof()。)

可以使用 "__dictoffset__""__weaklistoffset__" 成员类似地定义旧式的偏移量 tp_dictoffsettp_weaklistoffset,但强烈建议扩展使用 Py_TPFLAGS_MANAGED_DICTPy_TPFLAGS_MANAGED_WEAKREF

在 3.12 版本中更改: PyMemberDef 总是可用。之前,它需要包含 "structmember.h"

PyObject *PyMember_GetOne(const char *obj_addr, struct PyMemberDef *m)
属于 稳定 ABI 的一部分。

获取位于地址 obj_addr 的对象的属性。该属性由 PyMemberDef m 描述。发生错误时返回 NULL

在 3.12 版本中更改: PyMember_GetOne 总是可用。之前,它需要包含 "structmember.h"

int PyMember_SetOne(char *obj_addr, struct PyMemberDef *m, PyObject *o)
属于 稳定 ABI 的一部分。

将位于地址 obj_addr 的对象的属性设置为对象 o。要设置的属性由 PyMemberDef m 描述。如果成功则返回 0,失败则返回负值。

在 3.12 版本中更改: PyMember_SetOne 总是可用。之前,它需要包含 "structmember.h"

成员标志

以下标志可与 PyMemberDef.flags 一起使用

Py_READONLY

不可写。

Py_AUDIT_READ

在读取之前发出一个 object.__getattr__ 审计事件

Py_RELATIVE_OFFSET

表示此 PyMemberDef 条目的 offset 指示从子类特定的数据开始的偏移量,而不是从 PyObject 开始的偏移量。

当使用负的 basicsize 创建类时,只能作为 Py_tp_members slot 的一部分使用。在这种情况下,它是强制性的。

此标志仅在 PyType_Slot 中使用。在类创建期间设置 tp_members 时,Python 会清除它并将 PyMemberDef.offset 设置为从 PyObject 结构开始的偏移量。

在 3.10 版本中更改: #include "structmember.h" 可用的 RESTRICTEDREAD_RESTRICTEDWRITE_RESTRICTED 宏已被弃用。READ_RESTRICTEDRESTRICTED 等同于 Py_AUDIT_READWRITE_RESTRICTED 不执行任何操作。

在 3.12 版本中更改: READONLY 宏已重命名为 Py_READONLYPY_AUDIT_READ 宏已使用 Py_ 前缀重命名。现在,新的名称始终可用。以前,这些需要 #include "structmember.h"。该头文件仍然可用,它提供了旧的名称。

成员类型

PyMemberDef.type 可以是以下对应于各种 C 类型的宏之一。当在 Python 中访问成员时,它将被转换为等效的 Python 类型。当从 Python 设置时,它将转换回 C 类型。如果不可能,则会引发诸如 TypeErrorValueError 之类的异常。

除非标记为 (D),否则无法使用例如 deldelattr() 删除以此方式定义的属性。

宏名称

C 类型

Python 类型

Py_T_BYTE

char

int

Py_T_SHORT

short

int

Py_T_INT

int

int

Py_T_LONG

long

int

Py_T_LONGLONG

long long

int

Py_T_UBYTE

unsigned char

int

Py_T_UINT

unsigned int

int

Py_T_USHORT

unsigned short

int

Py_T_ULONG

unsigned long

int

Py_T_ULONGLONG

unsigned long long

int

Py_T_PYSSIZET

Py_ssize_t

int

Py_T_FLOAT

float

float

Py_T_DOUBLE

double

float

Py_T_BOOL

char (表示为 0 或 1)

bool

Py_T_STRING

const char* (*)

str (只读)

Py_T_STRING_INPLACE

const char[] (*)

str (只读)

Py_T_CHAR

char (0-127)

str (**)

Py_T_OBJECT_EX

PyObject*

object (D)

(*): 以空字符结尾、UTF8 编码的 C 字符串。对于 Py_T_STRING,C 表示形式是指针;对于 Py_T_STRING_INPLACE,字符串直接存储在结构中。

(**): 长度为 1 的字符串。仅接受 ASCII 字符。

(只读): 意味着 Py_READONLY

(D): 可以删除,在这种情况下,指针设置为 NULL。读取 NULL 指针会引发 AttributeError

3.12 版本新增: 在之前的版本中,宏只能通过 #include "structmember.h" 使用,并且没有 Py_ 前缀(例如,T_INT)。头文件仍然可用,并且包含旧名称,以及以下已弃用的类型

T_OBJECT

类似于 Py_T_OBJECT_EX,但 NULL 会转换为 None。这会导致 Python 中出现令人惊讶的行为:删除属性实际上会将其设置为 None

T_NONE

始终为 None。必须与 Py_READONLY 一起使用。

定义 Getters 和 Setters

type PyGetSetDef
属于 稳定 ABI 的一部分(包括所有成员)。

用于为类型定义类似属性的访问的结构。另请参阅 PyTypeObject.tp_getset 插槽的描述。

const char *name

属性名称

getter get

用于获取属性的 C 函数。

setter set

用于设置或删除属性的可选 C 函数。如果为 NULL,则该属性为只读。

const char *doc

可选的文档字符串

void *closure

可选的用户数据指针,为 getter 和 setter 提供额外数据。

typedef PyObject *(*getter)(PyObject*, void*)
属于 稳定 ABI 的一部分。

get 函数接受一个 PyObject* 参数(实例)和一个用户数据指针(关联的 closure)。

成功时应返回新引用,失败时应返回 NULL 并设置异常。

typedef int (*setter)(PyObject*, PyObject*, void*)
属于 稳定 ABI 的一部分。

set 函数接受两个 PyObject* 参数(实例和要设置的值)和一个用户数据指针(关联的 closure)。

如果应删除该属性,则第二个参数为 NULL。成功时应返回 0,失败时应返回 -1 并设置异常。