公用对象结构体

大量的结构体被用于定义Python的对象类型。这一节描述了这些的结构体和它们的使用方法。

基本的对象类型和宏

所有的 Python 对象最终都会在对象的内存表示的开始部分共享少量的字段。 这些字段由 PyObjectPyVarObject 类型来表示,相应地,这些类型又是由一些宏扩展来定义的,它们也直接或间接地被用于所有其他 Python 对象的定义。 附加的宏可以在 引用计数 下找到。

type PyObject

Part of the Limited API. (Only some members are part of the stable ABI.)

所有对象类型都是此类型的扩展。 这是一个包含了 Python 将对象的指针当作对象来处理所需的信息的类型。 在一个普通的“发行”编译版中,它只包含对象的引用计数和指向对应类型对象的指针。 没有什么对象被实际声明为 PyObject,但每个指向 Python 对象的指针都可以被转换为 PyObject*。 对成员的访问必须通过使用 Py_REFCNTPy_TYPE 宏来完成。

type PyVarObject

Part of the Limited API. (Only some members are part of the stable ABI.)

这是一个添加了 ob_size 字段的 PyObject 扩展。 它仅用于具有某些 长度 标记的对象。 此类型并不经常在 Python/C API 中出现。 对成员的访问必须通过使用 Py_REFCNT, Py_TYPEPy_SIZE 宏来完成。

PyObject_HEAD

这是一个在声明代表无可变长度对象的新类型时所使用的宏。 PyObject_HEAD 宏被扩展为:

  1. PyObject ob_base;

参见上面 PyObject 的文档。

PyObject_VAR_HEAD

这是一个在声明代表每个实例具有可变长度的对象时所使用的宏。 PyObject_VAR_HEAD 宏被扩展为:

  1. PyVarObject ob_base;

参见上面 PyVarObject 的文档。

int Py_Is(PyObject *x, PyObject *y)

Part of the Stable ABI since version 3.10.

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

3.10 新版功能.

int Py_IsNone(PyObject *x)

Part of the Stable ABI since version 3.10.

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

3.10 新版功能.

int Py_IsTrue(PyObject *x)

Part of the Stable ABI since version 3.10.

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

3.10 新版功能.

int Py_IsFalse(PyObject *x)

Part of the Stable ABI since version 3.10.

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

3.10 新版功能.

PyTypeObject *Py_TYPE(PyObject *o)

获取 Python 对象 o 的类型。

返回一个 borrowed reference

使用 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 类型扩展初始化值的宏。 该宏扩展为:

  1. _PyObject_EXTRA_INIT
  2. 1, type,

PyVarObject_HEAD_INIT(type, size)

这是一个为新的 PyVarObject 类型扩展初始化值的宏,包括 ob_size 字段。 该宏会扩展为:

  1. _PyObject_EXTRA_INIT
  2. 1, type, size,

实现函数和方法

type PyCFunction

Part of the Stable ABI.

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

函数的签名为:

  1. PyObject *PyCFunction(PyObject *self,
  2. PyObject *args);

type PyCFunctionWithKeywords

Part of the Stable ABI.

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

  1. PyObject *PyCFunctionWithKeywords(PyObject *self,
  2. PyObject *args,
  3. PyObject *kwargs);

type _PyCFunctionFast

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

  1. PyObject *_PyCFunctionFast(PyObject *self,
  2. PyObject *const *args,
  3. Py_ssize_t nargs);

type _PyCFunctionFastWithKeywords

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

  1. PyObject *_PyCFunctionFastWithKeywords(PyObject *self,
  2. PyObject *const *args,
  3. Py_ssize_t nargs,
  4. PyObject *kwnames);

type PyCMethod

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

  1. PyObject *PyCMethod(PyObject *self,
  2. PyTypeObject *defining_class,
  3. PyObject *const *args,
  4. Py_ssize_t nargs,
  5. PyObject *kwnames)

3.9 新版功能.

type PyMethodDef

Part of the Stable ABI (including all members).

用于描述一个扩展类型的方法的结构体。 该结构体有四个字段:

  • 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_KEYWORDS, METH_FASTCALL | METH_KEYWORDSMETH_METHOD | METH_FASTCALL | METH_KEYWORDS

METH_VARARGS | METH_KEYWORDS

带有这些旗标的方法必须为 PyCFunctionWithKeywords 类型。 该函数接受三个形参: self, args, kwargs 其中 kwargs 是一个包含所有关键字参数的字典或者如果没有关键字参数则可以为 NULL。 这些形参通常是使用 PyArg_ParseTupleAndKeywords() 来处理的。

METH_FASTCALL

快速调用惯例仅支持位置参数。 这些方法的类型为 _PyCFunctionFast。 第一个形参为 self,第二个形参是由表示参数的 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 类型,与在 self 之后添加了 defining_class 参数的 METH_FASTCALL | METH_KEYWORDS 一样。

3.9 新版功能.

METH_NOARGS

如果通过 METH_NOARGS 旗标列出了参数则没有形参的方法无需检查是否给出了参数。 它们必须为 PyCFunction 类型。 第一个形参通常被命名为 self 并将持有对模块或对象实例的引用。 在所有情况下第二个形参都将为 NULL

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

METH_O

具有一个单独对象参数的方法可使用 METH_O 旗标列出,而不必发起调用 PyArg_ParseTuple() 并附带 "O" 参数。 它们的类型为 PyCFunction,带有 self 形参,以及代表该单独参数的 PyObject* 形参。

这两个常量不是被用来指明调用惯例而是在配合类方法使用时指明绑定。 它们不会被用于在模块上定义的函数。 对于任何给定方法这些旗标最多只会设置其中一个。

METH_CLASS

该方法将接受类型对象而不是类型的实例作为第一个形参。 它会被用于创建 类方法,类似于使用 classmethod() 内置函数所创建的结果。

METH_STATIC

该方法将接受 NULL 而不是类型的实例作为第一个形参。 它会被用于创建 静态方法,类似于使用 staticmethod() 内置函数所创建的结果。

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

METH_COEXIST

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

访问扩展类型的属性

type PyMemberDef

Part of the Stable ABI (including all members).

描述某个 C 结构成员对应类型的属性的结构体。 在定义类时,要把由这些结构组成的以 NULL 结尾的数组 放在 tp_members 槽位中。

其中的字段及顺序如下:

  • const char *name

    成员名称。 NULL 值表示 PyMemberDef[] 数组的结束。

    字符串应当是静态的,它不会被复制。

  • Py_ssize_t offset

    成员在类型的对象结构体中所在位置的以字节为单位的偏移量。

  • int type

    C 结构体中成员的类型。 请参阅 成员类型 了解可能的取值。

  • int flags

    零个或多个 成员旗标,使用按位或运算进行组合。

  • const char *doc

    文档字符串,或者为空。 该字符串应当是静态的,它不会被拷贝。 通常,它是使用 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 来定义,例如:

  1. static PyMemberDef spam_type_members[] = {
  2. {"__vectorcalloffset__", Py_T_PYSSIZET,
  3. offsetof(Spam_object, vectorcall), Py_READONLY},
  4. {NULL} /* Sentinel */
  5. };

(您可能需要为 offsetof() 添加 #include <stddef.h>。)

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

在 3.12 版更改: PyMemberDef 将始终可用。在之前版本中,它需要包括 "structmember.h"

PyObject *PyMember_GetOne(const char *obj_addr, struct PyMemberDef *m)

Part of the Stable ABI.

获取属于地址Get an attribute belonging to the object at address obj_addr 上的对象的某个属性。 该属性是以 PyMemberDef m 来描述的。 出错时返回 NULL

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

int PyMember_SetOne(char *obj_addr, struct PyMemberDef *m, PyObject *o)

Part of the Stable 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 槽位 的组成部分。 它在此种情况下是强制要求。

这个旗标只能在 PyTypeSlot 中使用。 在类创建期间中设置 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 (RO)

    Py_T_STRING_INPLACE

const char[] ()

str (RO)

    Py_T_CHAR

char (0-127)

str (**)

    Py_T_OBJECT_EX

PyObject

object (D)

(*): 以零结束的 UTF8 编码的 C 字符串。 使用:c:macro:!Py_T_STRING 时的 C 表示形式是指针;使用 Py_T_STRING_INLINE 时字符串将直接存储在结构体中。

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

(RO):表示 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 一起使用。

定义读取器和设置器

type PyGetSetDef

Part of the Stable ABI (including all members).

用于定义针对某个类型的特征属性式的访问的结构体。 另请参阅 PyTypeObject.tp_getset 槽位的描述。

  • const char *name

    属性名称

  • getter get

    用于获取属性的 C 函数。

  • setter set

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

  • const char *doc

    可选的文档字符串

  • void *closure

    可选的函数指针,为 getter 和 setter 提供附加数据。

get 函数接受一个 PyObject* 形参 (实例) 和一个函数指针 (关联的 closure):

  1. typedef PyObject *(*getter)(PyObject *, void *);

它应当在成功时返回一个新的引用或在失败时返回 NULL 并设置异常。

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

  1. typedef int (*setter)(PyObject *, PyObject *, void *);

对于属性要被删除的情况第二个形参应为 NULL。 成功时应返回 0 或在失败时返回 -1 并设置异常。