公用对象结构体¶
大量的结构体被用于定义Python的对象类型。这一节描述了这些的结构体和它们的使用方法。
基本的对象类型和宏¶
所有的 Python 对象都在对象的内存表示的开始部分共享少量的字段。 这些字段用 PyObject
或 PyVarObject
类型来表示,这些类型又由一些宏定义,这些宏也直接或间接地用于所有其他 Python 对象的定义。
-
type PyObject¶
- Part of the Limited API. (Only some members are part of the stable ABI.)
所有对象类型都是此类型的扩展。 这是一个包含了 Python 将对象的指针当作对象来处理所需的信息的类型。 在一个普通的“发行”编译版中,它只包含对象的引用计数和指向对应类型对象的指针。 没有什么对象被实际声明为
PyObject
,但每个指向 Python 对象的指针都可以被转换为 PyObject*。 对成员的访问必须通过使用Py_REFCNT
和Py_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_TYPE
和Py_SIZE
宏来完成。
-
PyObject_HEAD¶
这是一个在声明代表无可变长度对象的新类型时所使用的宏。 PyObject_HEAD 宏被扩展为:
PyObject ob_base;
参见上面
PyObject
的文档。
-
PyObject_VAR_HEAD¶
这是一个在声明代表每个实例具有可变长度的对象时所使用的宏。 PyObject_VAR_HEAD 宏被扩展为:
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()
函数来设置一个对象类型。
-
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(PyObject *o)¶
获取 Python 对象 o 的引用计数。
使用
Py_SET_REFCNT()
函数来设置一个对象引用计数。在 3.11 版更改: 形参类型不再是 const PyObject*。
在 3.10 版更改:
Py_REFCNT()
被改为内联的静态函数。
-
void Py_SET_REFCNT(PyObject *o, Py_ssize_t refcnt)¶
将对象 o 的引用计数器设为 refcnt。
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¶
- Part of the Stable ABI.
用于在 C 中实现大多数 Python 可调用对象的函数类型。 该类型的函数接受两个 PyObject* 形参并返回一个这样的值。 如果返回值为
NULL
,则将设置一个异常。 如果不为NULL
,则返回值将被解读为 Python 中暴露的函数的返回值。 此函数必须返回一个新的引用。函数的签名为:
PyObject *PyCFunction(PyObject *self, PyObject *args);
-
type PyCFunctionWithKeywords¶
- Part of the Stable ABI.
用于在 C 中实现具有 METH_VARARGS | METH_KEYWORDS 签名的 Python 可调用对象的函数类型。 函数的签名为:
PyObject *PyCFunctionWithKeywords(PyObject *self, PyObject *args, PyObject *kwargs);
-
type _PyCFunctionFast¶
用于在 C 中实现具有
METH_FASTCALL
签名的 Python 可调用对象的函数类型。 函数的签名为:PyObject *_PyCFunctionFast(PyObject *self, PyObject *const *args, Py_ssize_t nargs);
-
type _PyCFunctionFastWithKeywords¶
用于在 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¶
- Part of the Stable ABI (including all members).
用于描述一个扩展类型的方法的结构体。 该结构体有四个字段:
-
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* 值组成的数组而第三个形参是参数的数量(数组的长度)。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 结构体成员相对应的类型的属性的结构体。 它的字段有:
域
C 类型
含意
name
const char *
成员名称
type
int
C 结构体中成员的类型
offset
Py_ssize_t
成员在类型的对象结构体中所在位置的以字节表示的偏移量
flags
int
指明字段是否应为只读或可写的旗标位
doc
const char *
指向文档字符串的内容
type
可以是与各种 C 类型相对应的许多T_
宏中的一个。 当在 Python 中访问该成员时,它将被转换为等价的 Python 类型。宏名称
C 类型
T_SHORT
short
T_INT
int
T_LONG
长整型
T_FLOAT
float
T_DOUBLE
double
T_STRING
const char *
T_OBJECT
PyObject *
T_OBJECT_EX
PyObject *
T_CHAR
char
T_BYTE
char
T_UBYTE
unsigned char
T_UINT
unsigned int
T_USHORT
unsigned short
T_ULONG
unsigned long
T_BOOL
char
T_LONGLONG
long long
T_ULONGLONG
unsigned long long
T_PYSSIZET
Py_ssize_t
T_OBJECT
和T_OBJECT_EX
的区别在于T_OBJECT
返回None
表示其成员为NULL
并且T_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_OBJECT
和T_OBJECT_EX
成员可以被删除。 (它们会被设为NULL
)。堆分配类型 (使用
PyType_FromSpec()
或类似函数创建),PyMemberDef
可以包含特殊成员__dictoffset__
,__weaklistoffset__
和__vectorcalloffset__
的定义,对应类型对象中的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)¶
获取属于地址Get an attribute belonging to the object at address obj_addr 上的对象的某个属性。 该属性是以
PyMemberDef
m 来描述的。 出错时返回NULL
。
-
int PyMember_SetOne(char *obj_addr, struct PyMemberDef *m, PyObject *o)¶
将属于位于地址 obj_addr 的对象的属性设置到对象 o。 要设置的属性由
PyMemberDef
m 描述。 成功时返回0
而失败时返回负值。
-
type PyGetSetDef¶
- Part of the Stable ABI (including all members).
用于定义针对某个类型的特征属性式的访问的结构体。 另请参阅
PyTypeObject.tp_getset
槽位的描述。域
C 类型
含意
name
const char *
属性名称
get
getter
用于获取属性的 C 函数
set
setter
用于设置或删除属性的可选 C 函数,如果省略则属性将为只读
doc
const char *
可选的文档字符串
closure
void *
可选的函数指针,为 getter 和 setter 提供附加数据
get
函数接受一个 PyObject* 形参 (实例) 和一个函数指针 (关联的closure
):typedef PyObject *(*getter)(PyObject *, void *);
它应当在成功时返回一个新的引用或在失败时返回
NULL
并设置异常。set
函数接受两个 PyObject* 形参 (实例和要设置的值) 和一个函数指针 (关联的closure
):typedef int (*setter)(PyObject *, PyObject *, void *);
对于属性要被删除的情况第二个形参应为
NULL
。 成功时应返回0
或在失败时返回-1
并设置异常。