通用对象结构

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

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

  • PyObject

    • 所有对象类型都是此类型的扩展。这种类型包含 Python 需要将指向对象的指针视为对象的信息。在普通的“发布”版本中,它仅包含对象的引用计数和指向相应类型对象的指针。它对应于PyObject_HEAD宏扩展定义的字段。
  • PyVarObject

    • 这是PyObject的 extensions,其中添加了ob_size字段。这仅用于具有* length *概念的对象。此类型通常不出现在 Python/C API 中。它对应于PyObject_VAR_HEAD宏扩展定义的字段。

这些宏用于PyObjectPyVarObject的定义:

  • PyObject_HEAD
    • 这是一个宏,扩展为PyObject类型的字段的语句;在语句表示对象的新类型而长度不变化时使用它。它扩展的特定字段取决于Py_TRACE_REFS的定义。默认情况下,未定义该宏,并且PyObject_HEAD扩展为:
Py_ssize_t ob_refcnt;
PyTypeObject *ob_type;

定义Py_TRACE_REFS后,它将扩展为:

PyObject *_ob_next, *_ob_prev;
Py_ssize_t ob_refcnt;
PyTypeObject *ob_type;
  • PyObject_VAR_HEAD
    • 这是一个宏,扩展为PyVarObject类型的字段的语句;在语句表示对象的长度不同实例的新类型时使用它。该宏始终扩展为:
PyObject_HEAD
Py_ssize_t ob_size;

请注意,PyObject_HEAD是扩展的一部分,其自身的扩展取决于Py_TRACE_REFS的定义而有所不同。

  • Py_TYPE(o)
    • 此宏用于访问 Python 对象的ob_type成员。它扩展为:
(((PyObject*)(o))->ob_type)

2.6 版的新Function。

  • Py_REFCNT(o)
    • 此宏用于访问 Python 对象的ob_refcnt成员。它扩展为:
(((PyObject*)(o))->ob_refcnt)

2.6 版的新Function。

  • Py_SIZE(o)
    • 此宏用于访问 Python 对象的ob_size成员。它扩展为:
(((PyVarObject*)(o))->ob_size)

2.6 版的新Function。

  • 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 中公开的函数的返回值。该函数必须返回一个新的引用。
  • PyMethodDef

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

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

ml_flags字段是一个位字段,可以包含以下标志。各个标志指示调用约定或绑定约定。在调用约定标志中,只能组合METH_VARARGSMETH_KEYWORDS。任何调用约定标志都可以与绑定标志结合使用。

  • METH_VARARGS

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

    • 具有这些标志的方法的类型必须为PyCFunctionWithKeywords。该函数需要三个参数:* self args *以及所有关键字参数的字典。该标志通常与METH_VARARGS组合,并且通常使用PyArg_ParseTupleAndKeywords()处理参数。
  • METH_NOARGS

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

  • METH_OLDARGS

    • 不建议使用此调用约定。该方法必须为PyCFunction类型。如果未提供任何参数,则第二个参数为* NULL *;如果仅给出一个参数,则为单个对象;如果给出多个参数,则为一个对象的 Tuples。使用此约定的函数无法区分具有多个参数的调用和具有 Tuples 作为唯一参数的调用。

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

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

2.3 版的新Function。

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

2.3 版的新Function。

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

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

2.4 版的新Function。

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

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

Macro nameC type
T_SHORTshort
T_INTint
T_LONGlong
T_FLOATfloat
T_DOUBLEdouble
T_STRINGchar *
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意味着READONLY。只能删除T_OBJECTT_OBJECT_EX成员。 (它们设置为* NULL *)。

  • PyGetSetDef
FieldC TypeMeaning
namechar *attribute name
getgetterC 函数获取属性
setsetter可选的 C 函数,用于设置或删除属性,如果Ellipsis,则该属性为只读
docchar *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

返回用 C 实现的扩展类型的绑定方法对象。这在不使用PyObject_GenericGetAttr()函数的tp_getattrotp_getattr处理程序的实现中很有用。