常用对象结构¶
Python 中定义对象类型时会用到大量的结构体。本节将描述这些结构体以及它们是如何使用的。
基本对象类型和宏¶
所有 Python 对象最终在内存中的对象表示的开头共享少量字段。这些字段由 PyObject
和 PyVarObject
类型表示,这些类型又由一些宏的扩展定义,这些宏直接或间接地用于定义所有其他 Python 对象。其他宏可以在 引用计数 下找到。
-
type PyObject¶
- 属于 有限 API 的一部分。(只有部分成员是稳定的 ABI 的一部分。)
所有对象类型都是此类型的扩展。这是一种包含 Python 将对象指针视为对象所需信息的类型。在正常的 “release” 版本中,它仅包含对象的引用计数和指向相应类型对象的指针。实际上没有声明为
PyObject
,但每个指向 Python 对象的指针都可以转换为 PyObject*。对成员的访问必须使用宏Py_REFCNT
和Py_TYPE
完成。
-
type PyVarObject¶
- 属于 有限 API 的一部分。(只有部分成员是稳定的 ABI 的一部分。)
这是
PyObject
的扩展,添加了ob_size
字段。这仅用于具有某种长度概念的对象。此类型在 Python/C API 中不常出现。对成员的访问必须使用宏Py_REFCNT
、Py_TYPE
和Py_SIZE
完成。
-
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()
函数设置对象类型。
-
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 版本中新增。
-
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¶
指向文档字符串的内容。
-
const char *ml_name¶
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_KEYWORDS 和 METH_METHOD | METH_FASTCALL | METH_KEYWORDS。
- METH_VARARGS | METH_KEYWORDS
具有这些标志的方法必须是
PyCFunctionWithKeywords
类型。该函数期望三个参数:self、args、kwargs,其中 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 字符串,它将用作定义该函数的模块的名称。如果不可用,可以将其设置为None
或NULL
。另请参阅
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[]
数组的末尾。该字符串应该是静态的,不会对其进行复制。
-
Py_ssize_t offset¶
成员在类型对象的结构体中所处的字节偏移量。
默认情况下(当
flags
为0
时),成员允许读写访问。对于只读访问,请使用Py_READONLY
标志。某些类型,如Py_T_STRING
,表示Py_READONLY
。只有Py_T_OBJECT_EX
(和旧式的T_OBJECT
)成员可以被删除。对于堆分配的类型(使用
PyType_FromSpec()
或类似方法创建),PyMemberDef
可能包含特殊成员"__vectorcalloffset__"
的定义,它对应于类型对象中的tp_vectorcall_offset
。这些必须使用Py_T_PYSSIZET
和Py_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_dictoffset
和tp_weaklistoffset
,但强烈建议扩展使用Py_TPFLAGS_MANAGED_DICT
和Py_TPFLAGS_MANAGED_WEAKREF
。在 3.12 版本中更改:
PyMemberDef
总是可用。之前,它需要包含"structmember.h"
。 -
const char *name¶
-
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_RELATIVE_OFFSET¶
表示此
PyMemberDef
条目的offset
指示从子类特定的数据开始的偏移量,而不是从PyObject
开始的偏移量。当使用负的
basicsize
创建类时,只能作为Py_tp_members
slot
的一部分使用。在这种情况下,它是强制性的。此标志仅在
PyType_Slot
中使用。在类创建期间设置tp_members
时,Python 会清除它并将PyMemberDef.offset
设置为从PyObject
结构开始的偏移量。
在 3.10 版本中更改: #include "structmember.h"
可用的 RESTRICTED
、READ_RESTRICTED
和 WRITE_RESTRICTED
宏已被弃用。READ_RESTRICTED
和 RESTRICTED
等同于 Py_AUDIT_READ
;WRITE_RESTRICTED
不执行任何操作。
在 3.12 版本中更改: READONLY
宏已重命名为 Py_READONLY
。PY_AUDIT_READ
宏已使用 Py_
前缀重命名。现在,新的名称始终可用。以前,这些需要 #include "structmember.h"
。该头文件仍然可用,它提供了旧的名称。
成员类型¶
PyMemberDef.type
可以是以下对应于各种 C 类型的宏之一。当在 Python 中访问成员时,它将被转换为等效的 Python 类型。当从 Python 设置时,它将转换回 C 类型。如果不可能,则会引发诸如 TypeError
或 ValueError
之类的异常。
除非标记为 (D),否则无法使用例如 del
或 delattr()
删除以此方式定义的属性。
宏名称 |
C 类型 |
Python 类型 |
---|---|---|
|
char |
|
|
short |
|
|
int |
|
|
long |
|
|
long long |
|
|
unsigned char |
|
|
unsigned int |
|
|
unsigned short |
|
|
unsigned long |
|
|
unsigned long long |
|
|
||
|
float |
|
|
double |
|
|
char (表示为 0 或 1) |
|
|
const char* (*) |
|
|
const char[] (*) |
|
|
char (0-127) |
|
|
|
(*): 以空字符结尾、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¶
属性名称
-
const char *doc¶
可选的文档字符串
-
void *closure¶
可选的用户数据指针,为 getter 和 setter 提供额外数据。
-
const char *name¶