通用对象结构¶
在 Python 对象类型的定义中使用了大量的结构。本节描述了这些结构及其用法。
基本对象类型和宏¶
所有 Python 对象最终在对象内存表示的开头共享少量字段。这些字段由 PyObject 和 PyVarObject 类型表示,而这些类型又由一些宏的扩展定义,这些宏直接或间接用于所有其他 Python 对象的定义。更多宏可在引用计数中找到。
-
类型 PyObject¶
- 有限 API 的一部分。(只有某些成员是稳定 ABI 的一部分。)
所有对象类型都是此类型的扩展。此类型包含 Python 将指向对象的指针视为对象所需的信息。在正常的“发布”构建中,它只包含对象的引用计数和指向相应类型对象的指针。实际上没有东西被声明为
PyObject,但指向 Python 对象的每个指针都可以转换为 PyObject*。成员不得直接访问;应使用
Py_REFCNT和Py_TYPE等宏。-
Py_ssize_t ob_refcnt¶
- 作为 稳定 ABI 的一部分。
对象的引用计数,由
Py_REFCNT返回。不要直接使用此字段;应使用函数和宏,例如Py_REFCNT、Py_INCREF()和Py_DecRef()。字段类型可能与
Py_ssize_t不同,具体取决于构建配置和平台。
-
PyTypeObject *ob_type¶
- 作为 稳定 ABI 的一部分。
对象的类型。不要直接使用此字段;应使用
Py_TYPE和Py_SET_TYPE()。
-
Py_ssize_t ob_refcnt¶
-
类型 PyVarObject¶
- 有限 API 的一部分。(只有某些成员是稳定 ABI 的一部分。)
这是
PyObject的扩展,它增加了ob_size字段。它用于具有某种“长度”概念的对象。与
PyObject一样,成员不得直接访问;应使用Py_SIZE、Py_REFCNT和Py_TYPE等宏。-
Py_ssize_t ob_size¶
- 作为 稳定 ABI 的一部分。
一个大小字段,其内容应被视为对象的内部实现细节。
不要直接使用此字段;应使用
Py_SIZE。对象创建函数,例如
PyObject_NewVar(),通常会将此字段设置为请求的大小(项目数)。创建后,可以使用Py_SET_SIZE将任意值存储到ob_size中。要获取对象的公共公开长度(由 Python 函数
len()返回),应使用PyObject_Length()。
-
Py_ssize_t ob_size¶
-
PyObject_VAR_HEAD¶
这是一个在声明具有可变长度的新对象类型时使用的宏。PyObject_VAR_HEAD 宏扩展为
PyVarObject ob_base;
请参阅上面
PyVarObject的文档。
-
PyTypeObject PyBaseObject_Type¶
- 作为 稳定 ABI 的一部分。
所有其他对象的基类,与 Python 中的
object相同。
-
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)¶
- 返回值:借用引用。自版本 3.14 起成为稳定 ABI 的一部分。
获取 Python 对象 *o* 的类型。
返回的引用是从 *o* 借用的。不要使用
Py_DECREF()或类似函数释放它。
-
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*,不进行任何检查或引用计数。
这是一个非常低级的操作。考虑改用
PyObject_SetAttrString()或类似函数设置 Python 属性__class__。请注意,分配不兼容的类型可能导致未定义行为。
如果 *type* 是堆类型,则调用者必须创建对其的新引用。类似地,如果 *o* 的旧类型是堆类型,则调用者必须释放对该类型的引用。
在 3.9 版本中新增。
-
Py_ssize_t Py_SIZE(PyVarObject *o)¶
获取 *o* 的
ob_size字段。版本 3.11 中已更改:
Py_SIZE()已更改为内联静态函数。参数类型不再是 const PyVarObject*。
-
void Py_SET_SIZE(PyVarObject *o, Py_ssize_t size)¶
将 *o* 的
ob_size字段设置为 *size*。在 3.9 版本中新增。
-
PyVarObject_HEAD_INIT(type, size)¶
这是一个宏,它扩展为新
PyVarObject类型的初始化值,包括ob_size字段。此宏扩展为_PyObject_EXTRA_INIT 1, type, size,
实现函数和方法¶
-
类型 PyCFunction¶
- 作为 稳定 ABI 的一部分。
用于在 C 中实现大多数 Python 可调用对象的函数类型。此类型的函数接受两个 PyObject* 参数并返回一个此类值。如果返回值为
NULL,则应已设置异常。如果不是NULL,则返回值被解释为函数在 Python 中公开的返回值。函数必须返回一个新的引用。函数签名是
PyObject *PyCFunction(PyObject *self, PyObject *args);
-
类型 PyCFunctionWithKeywords¶
- 作为 稳定 ABI 的一部分。
用于在 C 中实现具有签名 METH_VARARGS | METH_KEYWORDS 的 Python 可调用对象的函数类型。函数签名是
PyObject *PyCFunctionWithKeywords(PyObject *self, PyObject *args, PyObject *kwargs);
-
类型 PyCFunctionFast¶
- 自 3.13 版本起成为 稳定 ABI 的一部分。
用于在 C 中实现具有签名
METH_FASTCALL的 Python 可调用对象的函数类型。函数签名是PyObject *PyCFunctionFast(PyObject *self, PyObject *const *args, Py_ssize_t nargs);
-
类型 PyCFunctionFastWithKeywords¶
- 自 3.13 版本起成为 稳定 ABI 的一部分。
用于在 C 中实现具有签名 METH_FASTCALL | METH_KEYWORDS 的 Python 可调用对象的函数类型。函数签名是
PyObject *PyCFunctionFastWithKeywords(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames);
-
类型 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 版本中新增。
-
类型 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*,第二个参数是 PyObject* 值的 C 数组,指示参数,第三个参数是参数的数量(数组的长度)。在 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相同,但defining_class参数在self之后添加。在 3.9 版本中新增。
-
METH_NOARGS¶
不带参数的方法如果使用
METH_NOARGS标志列出,则无需检查是否提供了参数。它们需要是PyCFunction类型。第一个参数通常命名为 *self*,将持有对模块或对象实例的引用。在所有情况下,第二个参数都将为NULL。函数必须有两个参数。由于第二个参数未使用,可以使用
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)。
访问扩展类型的属性¶
-
类型 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或Py_READONLY | Py_RELATIVE_OFFSET。例如static PyMemberDef spam_type_members[] = { {"__vectorcalloffset__", Py_T_PYSSIZET, offsetof(Spam_object, vectorcall), Py_READONLY}, {NULL} /* Sentinel */ };
(您可能需要
#include <stddef.h>才能使用offsetof()。)旧版偏移量
tp_dictoffset和tp_weaklistoffset可以通过使用"__dictoffset__"和"__weaklistoffset__"成员类似地定义,但强烈建议扩展使用Py_TPFLAGS_MANAGED_DICT和Py_TPFLAGS_MANAGED_WEAKREF。版本 3.12 中已更改:
PyMemberDef始终可用。以前,它需要包含"structmember.h"。版本 3.14 中已更改:
Py_RELATIVE_OFFSET现在允许用于"__vectorcalloffset__"、"__dictoffset__"和"__weaklistoffset__"。 -
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的偏移量。只能作为
Py_tp_membersslot的一部分使用,当使用负basicsize创建类时。在这种情况下它是强制性的。此标志仅在
PyType_Slot中使用。在类创建期间设置tp_members时,Python 会清除它并将PyMemberDef.offset设置为从PyObject结构的偏移量。
版本 3.10 中已更改: RESTRICTED、READ_RESTRICTED 和 WRITE_RESTRICTED 宏(可通过 #include "structmember.h" 获得)已弃用。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 |
|
|
||
|
浮点数 |
|
|
double |
|
|
char (写入为 0 或 1) |
|
|
const char* (*) |
|
|
const char[] (*) |
|
|
char (0-127) |
|
|
|
(*): 以零终止的 UTF8 编码 C 字符串。对于
Py_T_STRING,C 表示是一个指针;对于Py_T_STRING_INPLACE,字符串直接存储在结构中。(**): 长度为 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一起使用。
定义获取器和设置器¶
-
类型 PyGetSetDef¶
- 稳定 ABI 的一部分(包括所有成员)。
用于为类型定义类似属性访问的结构。另请参阅
PyTypeObject.tp_getset槽的描述。-
const char *name¶
属性名称
-
const char *doc¶
可选文档字符串
-
void *closure¶
可选的用户数据指针,为 getter 和 setter 提供附加数据。
-
const char *name¶