通用对象结构

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

在内存中该对象表示的开头,所有 Python 对象finally都共享少量字段。这些由PyObjectPyVarObject类型表示,它们依次由在所有其他 Python 对象的定义中直接或间接使用的某些宏的扩展定义。

  • PyObject

    • 所有对象类型都是此类型的扩展。这种类型包含 Python 需要将指向对象的指针视为对象的信息。在普通的“发布”版本中,它仅包含对象的引用计数和指向相应类型对象的指针。实际上没有任何东西语句为PyObject,但是指向 Python 对象的每个指针都可以转换为PyObject*。必须使用宏Py_REFCNTPy_TYPE对成员进行访问。
  • PyVarObject

    • 这是PyObject的 extensions,其中添加了ob_size字段。这仅用于具有* length *概念的对象。此类型通常不出现在 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文档。

  • Py_TYPE(o)
    • 此宏用于访问 Python 对象的ob_type成员。它扩展为:
(((PyObject*)(o))->ob_type)
  • Py_REFCNT(o)
    • 此宏用于访问 Python 对象的ob_refcnt成员。它扩展为:
(((PyObject*)(o))->ob_refcnt)
  • Py_SIZE(o)
    • 此宏用于访问 Python 对象的ob_size成员。它扩展为:
(((PyVarObject*)(o))->ob_size)
  • PyObject_HEAD_INIT(类型)
    • 这是一个宏,扩展为新的PyObject类型的初始化值。该宏扩展为:
_PyObject_EXTRA_INIT
1, type,
  • PyVarObject_HEAD_INIT(类型,大小)
    • 这是一个宏,扩展为新的PyVarObject类型(包括ob_size字段)的初始化值。该宏扩展为:
_PyObject_EXTRA_INIT
1, type, size,
  • PyCFunction

    • 用于在 C 中实现大多数 Python 可调用对象的函数类型。此类函数采用两个PyObject*参数并返回一个这样的值。如果返回值为NULL,则应设置一个异常。如果不是NULL,则返回值将解释为 Python 中公开的函数的返回值。该函数必须返回一个新的引用。
  • PyCFunctionWithKeywords

    • 用于在 C 中使用签名METH_VARARGS | METH_KEYWORDS实现 Python 可调用函数的函数类型。
  • _PyCFunctionFast

    • 用于在 C 中使用签名METH_FASTCALL实现 Python 可调用函数的函数类型。
  • _PyCFunctionFastWithKeywords

    • 用于在 C 中使用签名METH_FASTCALL | METH_KEYWORDS实现 Python 可调用函数的函数类型。
  • PyMethodDef

    • 用于描述扩展类型的方法的结构。此结构包含四个字段:
FieldC TypeMeaning
ml_nameconst char *方法名称
ml_methPyCFunction指向 C 实现的指针
ml_flagsint标志位指示如何构造呼叫
ml_docconst char *指向文档字符串的内容

ml_meth是 C 函数指针。这些函数可能具有不同的类型,但它们始终返回PyObject*。如果该函数不是PyCFunction,则编译器将需要在方法表中进行强制转换。即使PyCFunction将第一个参数定义为PyObject*,方法实现通常也使用* self *对象的特定 C 类型。

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

位置参数有四个基本的调用约定,其中两个可以与METH_KEYWORDS组合以也支持关键字参数。因此,共有 6 个调用约定:

  • METH_VARARGS

    • 这是典型的调用约定,其中方法的类型为PyCFunction。该函数需要两个PyObject*值。第一个是方法的* self 对象;对于模块Function,它是模块对象。第二个参数(通常称为 args *)是表示所有参数的 Tuples 对象。通常使用PyArg_ParseTuple()PyArg_UnpackTuple()处理此参数。
  • METH_VARARGS | METH_KEYWORDS

    • 具有这些标志的方法的类型必须为PyCFunctionWithKeywords。该函数需要三个参数:* self args kwargs 其中 kwargs *是所有关键字参数的字典,如果没有关键字参数,则可能是NULL。通常使用PyArg_ParseTupleAndKeywords()处理参数。
  • METH_FASTCALL

    • 快速调用约定仅支持位置参数。这些方法的类型为_PyCFunctionFast。第一个参数是* self *,第二个参数是PyObject*个值的 C 数组,指示参数,而第三个参数是参数的数量(数组的长度)。

这不是limited API的一部分。

3.7 版中的新Function。

  • METH_FASTCALL | METH_KEYWORDS

    • METH_FASTCALL的 extensions 也支持关键字参数,类型为_PyCFunctionFastWithKeywords。关键字自变量的传递方式与引导调用协议中的传递方式相同:还有一个附加的PyObject*参数,它是表示关键字自变量名称的 Tuples,如果没有关键字,则可能是NULL。关键字参数的值存储在* args *数组中的位置参数之后。

这不是limited API的一部分。

3.7 版中的新Function。

  • METH_NOARGS

    • 没有参数的方法不需要检查是否使用METH_NOARGS标志列出了参数。它们必须为PyCFunction类型。第一个参数通常命名为* self *,它将保存对模块或对象实例的引用。在所有情况下,第二个参数均为NULL
  • METH_O

这两个常量不用于表示调用约定,而是用于类方法时的绑定。这些可能不适用于为模块定义的Function。对于任何给定的方法,最多只能设置这些标志之一。

  • METH_CLASS
    • 该方法将作为第一个参数而不是类型的实例传递给类型对象。这用于创建类方法,类似于使用classmethod()内置函数时创建的方法。
  • METH_STATIC
    • 该方法将被传递NULL作为第一个参数,而不是该类型的实例。这用于创建静态方法,类似于使用staticmethod()内置函数时创建的方法。

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

  • METH_COEXIST

    • 该方法将代替现有定义加载。如果没有* METH_COEXIST ,则默认为跳过重复的定义。由于插槽包装程序是在方法表之前加载的,因此,例如 sq_contains *插槽的存在将生成名为contains()的包装方法,并避免加载具有相同名称的相应 PyCFunction。定义了标志后,PyCFunction 将代替包装对象被加载,并与插槽共存。这很有用,因为对 PyCFunctions 的调用比对包装对象的调用进行了优化。
  • PyMemberDef

    • 描述对应于 C 结构成员的类型的属性的结构。它的字段是:
FieldC TypeMeaning
nameconst char *会员名称
typeintC 结构中成员的类型
offsetPy_ssize_t成员位于类型的对象 struct 上的偏移量(以字节为单位)
flagsint标志位,指示该字段是只读还是可写
docconst char *指向文档字符串的内容

type可以是与各种 C 类型相对应的T_宏之一。在 Python 中访问该成员时,该成员将转换为等效的 Python 类型。

Macro nameC type
T_SHORTshort
T_INTint
T_LONGlong
T_FLOATfloat
T_DOUBLEdouble
T_STRINGconst char *
T_OBJECTPyObject *
T_OBJECT_EXPyObject *
T_CHARchar
T_BYTEchar
T_UBYTEunsigned char
T_UINTunsigned int
T_USHORTunsigned short
T_ULONGunsigned long
T_BOOLchar
T_LONGLONGlong long
T_ULONGLONG无符号长久
T_PYSSIZETPy_ssize_t

T_OBJECTT_OBJECT_EX的不同之处在于,如果成员为NULL并且T_OBJECT_EX引发AttributeError,则T_OBJECT返回None。try使用T_OBJECT_EX而不是T_OBJECT,因为T_OBJECT_EX处理该属性上的del语句比使用T_OBJECT更正确。

flags可以是0(用于读写访问)或READONLY(用于只读访问)。为type使用T_STRING意味着READONLYT_STRING数据被解释为 UTF-8.只能删除T_OBJECTT_OBJECT_EX成员。 (它们设置为NULL)。

  • PyGetSetDef
FieldC TypeMeaning
nameconst char *attribute name
getgetterC 函数获取属性
setsetter可选的 C 函数,用于设置或删除属性,如果Ellipsis,则该属性为只读
docconst char *optional docstring
closurevoid *可选的函数指针,为 getter 和 setter 提供附加数据

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

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

如果成功,则应返回新的引用,如果失败,则应返回NULL,并返回设置的异常。

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

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

万一该属性应被删除,第二个参数是NULL。成功应返回0或失败应返回-1