通用对象结构 — Python 文档
通用对象结构
在 Python 的对象类型定义中使用了大量结构。 本节介绍这些结构以及如何使用它们。
基本对象类型和宏
所有 Python 对象最终在对象在内存中的表示开始时共享少量字段。 这些由 PyObject 和 PyVarObject 类型表示,这些类型又由一些宏的扩展来定义,这些宏在所有其他 Python 的定义中也直接或间接使用对象。
- type PyObject
- 所有对象类型都是这种类型的扩展。 这是一种包含 Python 需要将指向对象的指针视为对象的信息的类型。 在正常的“发布”构建中,它仅包含对象的引用计数和指向相应类型对象的指针。 实际上没有声明为 PyObject,但是每个指向 Python 对象的指针都可以转换为 PyObject*。 必须使用宏 Py_REFCNT 和 Py_TYPE 来访问成员。
- type PyVarObject
- 这是 PyObject 的扩展,添加了
ob_size
字段。 这仅用于具有 长度 某种概念的对象。 这种类型并不经常出现在 Python/C API 中。 必须使用宏 Py_REFCNT、Py_TYPE 和 Py_SIZE 来访问成员。
- PyObject_HEAD
这是在声明表示没有变化长度的对象的新类型时使用的宏。 PyObject_HEAD 宏扩展为:
PyObject ob_base;
请参阅上面的 PyObject 文档。
- PyObject_VAR_HEAD
这是在声明新类型时使用的宏,这些新类型表示长度因实例而异的对象。 PyObject_VAR_HEAD 宏扩展为:
PyVarObject ob_base;
请参阅上面的 PyVarObject 文档。
- Py_TYPE(o)
该宏用于访问 Python 对象的
ob_type
成员。 它扩展为:(((PyObject*)(o))->ob_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 类型设置为 类型 。
3.9 版中的新功能。
- Py_REFCNT(o)
该宏用于访问 Python 对象的
ob_refcnt
成员。 它扩展为:(((PyObject*)(o))->ob_refcnt)
- void Py_SET_REFCNT(PyObject *o, Py_ssize_t refcnt)
将对象 o 引用计数器设置为 refcnt。
3.9 版中的新功能。
- Py_SIZE(o)
该宏用于访问 Python 对象的
ob_size
成员。 它扩展为:(((PyVarObject*)(o))->ob_size)
- void Py_SET_SIZE(PyVarObject *o, Py_ssize_t size)
将对象 o 的大小设置为 大小。
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
用于在 C 中实现大多数 Python 可调用函数的函数类型。 这种类型的函数采用两个 PyObject* 参数并返回一个这样的值。 如果返回值为
NULL
,则应设置异常。 如果不是NULL
,则返回值被解释为 Python 中公开的函数的返回值。 该函数必须返回一个新的引用。函数签名是:
PyObject *PyCFunction(PyObject *self, PyObject *args);
- type PyCFunctionWithKeywords
用于在 C 中实现 Python 可调用函数的函数类型,签名为
METH_VARARGS | METH_KEYWORDS
。 函数签名是:PyObject *PyCFunctionWithKeywords(PyObject *self, PyObject *args, PyObject *kwargs);
- type _PyCFunctionFast
用于在 C 中实现 Python 可调用函数的函数类型,签名为 METH_FASTCALL。 函数签名是:
PyObject *_PyCFunctionFast(PyObject *self, PyObject *const *args, Py_ssize_t nargs);
- type _PyCFunctionFastWithKeywords
用于在 C 中实现 Python 可调用函数的函数类型,签名为
METH_FASTCALL | METH_KEYWORDS
。 函数签名是:PyObject *_PyCFunctionFastWithKeywords(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames);
- type PyCMethod
用于在 C 中实现 Python 可调用函数的函数类型,签名为
METH_METHOD | METH_FASTCALL | METH_KEYWORDS
。 函数签名是:PyObject *PyCMethod(PyObject *self, PyTypeObject *defining_class, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
3.9 版中的新功能。
- type PyMethodDef
用于描述扩展类型方法的结构。 这个结构有四个字段:
场地
C型
意义
ml_name
常量字符 *
方法名称
ml_meth
函数
指向 C 实现的指针
ml_flags
整数
指示应如何构造调用的标志位
ml_doc
常量字符 *
指向文档字符串的内容
ml_meth
是一个 C 函数指针。 函数可能是不同的类型,但它们总是返回 PyObject*。 如果函数不是 PyCFunction,编译器将需要在方法表中进行强制转换。 尽管 PyCFunction 将第一个参数定义为 PyObject*,但通常方法实现使用 self 对象的特定 C 类型。
ml_flags
字段是一个位字段,可以包含以下标志。 各个标志指示调用约定或绑定约定。
有这些调用约定:
- METH_VARARGS
- 这是典型的调用约定,其中方法的类型为 PyCFunction。 该函数需要两个 PyObject* 值。 第一个是方法的 self 对象; 对于模块函数,它是模块对象。 第二个参数(通常称为 args)是一个表示所有参数的元组对象。 此参数通常使用 PyArg_ParseTuple() 或 PyArg_UnpackTuple() 处理。
- METH_VARARGS | METH_KEYWORDS
- 具有这些标志的方法必须是 PyCFunctionWithKeywords 类型。 该函数需要三个参数:self、args、kwargs 其中 kwargs 是所有关键字参数的字典,也可能是
NULL
如果没有关键字参数。 通常使用 PyArg_ParseTupleAndKeywords() 处理参数。
- METH_FASTCALL
仅支持位置参数的快速调用约定。 这些方法的类型为 _PyCFunctionFast。 第一个参数是 self,第二个参数是 PyObject* 值的 C 数组,表示参数,第三个参数是参数的数量(数组的长度)。
这不是 受限 API 的一部分。
3.7 版中的新功能。
- METH_FASTCALL | METH_KEYWORDS
METH_FASTCALL 的扩展也支持关键字参数,方法类型为 _PyCFunctionFastWithKeywords。 关键字参数的传递方式与 vectorcall 协议 中的相同:还有一个额外的第四个 PyObject* 参数,它是一个表示关键字参数名称的元组(保证是字符串)或可能
NULL
如果没有关键字。 关键字参数的值存储在 args 数组中,在位置参数之后。这不是 受限 API 的一部分。
3.7 版中的新功能。
- METH_METHOD | METH_FASTCALL | METH_KEYWORDS
METH_FASTCALL | METH_KEYWORDS
的扩展支持 [X38X] 定义类 ,即包含相关方法的类。 定义类可能是Py_TYPE(self)
的超类。该方法需要是 PyCMethod 类型,与
METH_FASTCALL | METH_KEYWORDS
相同,在self
之后添加defining_class
参数。3.9 版中的新功能。
- METH_NOARGS
- 如果参数与 METH_NOARGS 标志一起列出,则没有参数的方法不需要检查是否给出了参数。 它们需要是 PyCFunction 类型。 第一个参数通常命名为 self 并且将保存对模块或对象实例的引用。 在所有情况下,第二个参数都是
NULL
。
- 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 的调用比包装器对象调用更优化。
访问扩展类型的属性
- type PyMemberDef
描述与 C 结构成员对应的类型的属性的结构。 它的字段是:
场地
C型
意义
name
常量字符 *
会员姓名
type
整数
C 结构体中成员的类型
offset
py_ssize_t
成员在类型的对象结构上的偏移量(以字节为单位)
flags
整数
指示字段是只读还是可写的标志位
doc
常量字符 *
指向文档字符串的内容
type
可以是对应于各种 C 类型的许多T_
宏之一。 在 Python 中访问该成员时,它会被转换为等效的 Python 类型。宏名称
C型
T_SHORT
短的
着色
整数
T_LONG
长
T_FLOAT
漂浮
T_DOUBLE
双倍的
T_STRING
常量字符 *
T_OBJECT
对象 *
T_OBJECT_EX
对象 *
T_CHAR
字符
T_BYTE
字符
T_UBYTE
无符号字符
T_UINT
无符号整数
T_USHORT
无符号短
T_ULONG
无符号长
T_BOOL
字符
T_LONGLONG
长长的
T_ULONGLONG
无符号长长
T_PYSSIZET
py_ssize_t
T_OBJECT
和T_OBJECT_EX
的不同在于T_OBJECT
返回None
如果成员是NULL
和T_OBJECT_EX
引发 ]属性错误。 尝试在T_OBJECT
上使用T_OBJECT_EX
,因为T_OBJECT_EX
比T_OBJECT
更正确地处理对该属性的 del 语句的使用。flags
可以是0
用于读写访问或READONLY
用于只读访问。 将T_STRING
用于 type 意味着READONLY
。T_STRING
数据被解释为 UTF-8。 只能删除T_OBJECT
和T_OBJECT_EX
成员。 (它们被设置为NULL
)。堆分配类型(使用 PyType_FromSpec() 或类似方法创建),
PyMemberDef
可能包含特殊成员__dictoffset__
、__weaklistoffset__
和 [ X163X],对应类型对象中的tp_dictoffset、tp_weaklistoffset和tp_vectorcall_offset。 这些必须用T_PYSSIZET
和READONLY
定义,例如:static PyMemberDef spam_type_members[] = { {"__dictoffset__", T_PYSSIZET, offsetof(Spam_object, dict), READONLY}, {NULL} /* Sentinel */ };
- PyObject *PyMember_GetOne(const char *obj_addr, struct PyMemberDef *m)
- 获取属于地址 obj_addr 处的对象的属性。 该属性由
PyMemberDef
m 描述。 出错时返回NULL
。
- int PyMember_SetOne(char *obj_addr, struct PyMemberDef *m, PyObject *o)
- 将属于地址 obj_addr 处的对象的属性设置为对象 o。 要设置的属性由
PyMemberDef
m 描述。 如果成功返回0
,失败返回负值。
- type PyGetSetDef
为类型定义类似属性的访问的结构。 另请参阅 PyTypeObject.tp_getset 插槽的描述。
场地
C型
意义
名称
常量字符 *
属性名
得到
吸气剂
C函数获取属性
放
二传手
可选的 C 函数来设置或删除属性,如果省略该属性是只读的
文档
常量字符 *
可选的文档字符串
关闭
空白 *
可选的函数指针,为 getter 和 setter 提供额外的数据
get
函数接受一个 PyObject* 参数(实例)和一个函数指针(关联的closure
):typedef PyObject *(*getter)(PyObject *, void *);
它应该在成功时返回一个新的引用,或者在失败时返回
NULL
并设置异常。set
函数采用两个 PyObject* 参数(实例和要设置的值)和一个函数指针(关联的closure
):typedef int (*setter)(PyObject *, PyObject *, void *);
如果属性应该被删除,第二个参数是
NULL
。 成功时应返回0
或失败时返回-1
并设置异常。