公共对象结构

在定义Python的对象类型时,使用了大量的结构。本节介绍这些结构及其使用方法。

基本对象类型和宏

所有的python对象最终在对象在内存中表示的开头共享少量的字段。它们由 PyObjectPyVarObject 类型,这些类型又由一些宏的扩展来定义,无论是直接还是间接地,在所有其他python对象的定义中也使用这些宏。

type PyObject

所有对象类型都是此类型的扩展。这是一个包含Python将对象指针视为对象所需信息的类型。在正常的“发布”构建中,它只包含对象的引用计数和指向相应类型对象的指针。实际上没有任何东西被声明为 PyObject 但每个指向python对象的指针都可以强制转换为 PyObject* . 必须使用宏来访问成员 Py_REFCNTPy_TYPE .

type PyVarObject

这是对 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 上面。

PyTypeObject *Py_TYPE(const PyObject *o)

获取Python对象的类型 o .

返回一个 borrowed reference

这个 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_REFCNT(const PyObject *o)

获取Python对象的引用计数 o .

在 3.10 版更改: Py_REFCNT() 更改为内联静态函数。使用 Py_SET_REFCNT() 设置对象引用计数。

void Py_SET_REFCNT(PyObject *o, Py_ssize_t refcnt)

设置对象 o 参考计数器 引用计数 .

3.9 新版功能.

Py_ssize_t Py_SIZE(const PyVarObject *o)

获取Python对象的大小 o .

这个 Py_SET_SIZE() 函数必须用于设置对象大小。

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

用于在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

PyCFunction

指向C实现的指针

ml_flags

int

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

ml_doc

常量字符 *

指向docstring的内容

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

这个 ml_flags 字段是可以包含以下标志的位字段。各个标志指示调用约定或绑定约定。

有以下调用约定:

METH_VARARGS

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

METH_VARARGS | METH_KEYWORDS

具有这些标志的方法的类型必须为 PyCFunctionWithKeywords . 函数需要三个参数: selfargs关键字参数 在哪里? 关键字参数 是所有关键字参数的字典,或者可能是 NULL 如果没有关键字参数。通常使用 PyArg_ParseTupleAndKeywords() .

METH_FASTCALL

仅支持位置参数的快速调用约定。方法具有类型 _PyCFunctionFast . 第一个参数是 self ,第二个参数是 PyObject* 指示参数的值和第三个参数是参数的数目(数组的长度)。

3.7 新版功能.

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

METH_FASTCALL | METH_KEYWORDS

延期 METH_FASTCALL 还支持关键字参数,方法类型为 _PyCFunctionFastWithKeywords . 关键字参数的传递方式与 vectorcall protocol :还有第四个 PyObject* 参数,它是一个元组,表示关键字参数的名称(保证为字符串),或者 NULL 如果没有关键字。关键字参数的值存储在 args 数组,在位置参数之后。

这不是 limited API .

3.7 新版功能.

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 .

METH_O

具有单个对象参数的方法可以与 METH_O 标记,而不是调用 PyArg_ParseTuple() 用一个 "O" 争论。他们有这种类型 PyCFunctionself 参数,以及 PyObject* 表示单个参数的参数。

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

METH_CLASS

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

METH_STATIC

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

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

METH_COEXIST

将加载该方法以取代现有的定义。没有 METH_COEXIST ,默认值是跳过重复的定义。由于槽封装器在方法表之前加载,因此 sq_contains 例如,slot将生成一个名为 __contains__() 并排除加载具有相同名称的相应PycFunction。定义了标志后,PycFunction将代替封装器对象加载,并与槽共存。这很有用,因为对pycfunctions的调用比封装对象调用优化得多。

访问扩展类型的属性

type PyMemberDef

结构,它描述与C结构成员对应的类型的属性。它的领域是:

C型

意义

name

常量字符 *

成员的姓名

type

int

C结构中成员的类型

offset

Py_ssize_t

成员位于类型的对象结构上的偏移量(以字节为单位)

flags

int

指示字段是只读还是可写的标志位

doc

常量字符 *

指向docstring的内容

type 可以是很多人中的一个 T_ 与各种C类型相对应的宏。当在python中访问该成员时,它将转换为等效的python类型。

宏名称

C型

T_SHORT

短的

T_INT

int

T_LONG

长的

T_FLOAT

浮动

T_DOUBLE

双重的

T_STRING

常量字符 *

T_OBJECT

PyObject *

T_OBJECT_EX

PyObject *

T_CHAR

烧焦

T_BYTE

烧焦

T_UBYTE

无符号字符

T_UINT

无符号整型

T_USHORT

无符号短整型

T_ULONG

无符号长

T_BOOL

烧焦

T_LONGLONG

长长

T_ULONGLONG

无符号长整型

T_PYSSIZET

Py_ssize_t

T_OBJECTT_OBJECT_EX 不同之处在于 T_OBJECT 收益率 None 如果成员是 NULLT_OBJECT_EX 提出一个 AttributeError . 尝试使用 T_OBJECT_EX 结束 T_OBJECT 因为 T_OBJECT_EX 处理的使用 del 对该属性的声明比 T_OBJECT .

flags 可以是 0 用于读写访问或 READONLY 用于只读访问。使用 T_STRING 对于 type 暗示 READONLY . T_STRING 数据被解释为UTF-8。只有 T_OBJECTT_OBJECT_EX 可以删除成员。(设置为 NULL

堆分配类型(使用 PyType_FromSpec() 或类似的), PyMemberDef 可包含特殊成员的定义 __dictoffset____weaklistoffset____vectorcalloffset__ ,对应于 tp_dictoffsettp_weaklistoffsettp_vectorcall_offset 在类型对象中。必须用 T_PYSSIZETREADONLY 例如:

static PyMemberDef spam_type_members[] = {
    {"__dictoffset__", T_PYSSIZET, offsetof(Spam_object, dict), READONLY},
    {NULL}  /* Sentinel */
};
type PyGetSetDef

用于定义类型的访问等属性的结构。另请参见 PyTypeObject.tp_getset 狭槽。

C型

意义

名称

常量字符 *

属性名

得到

吸气剂

C函数获取属性

设置

设定器

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

doc

常量字符 *

可选文档字符串

关闭

无效 *

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

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

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

它应该在成功时返回一个新的引用,或者 NULL 失败时出现设置异常。

set 功能需要两个 PyObject* 参数(实例和要设置的值)和函数指针(关联的 closure ):

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

如果应删除属性,则第二个参数是 NULL . 应该返回 0 关于成功还是 -1 失败时出现设置异常。