# 通用物件結構

大量的结构体被用于定义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.)

  这是一个 `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` 的文档。

int `Py_Is`(const PyObject *x, const PyObject *y)
  Part of the Stable ABI since version 3.10.

  测试 x 是否为 y 对象，与 Python 中的 `x is y` 相同。

  3.10 版新加入.

int `Py_IsNone`(const PyObject *x)
  Part of the Stable ABI since version 3.10.

  测试一个对象是否为 `None` 单例，与 Python 中的 `x is None` 相同。

  3.10 版新加入.

int `Py_IsTrue`(const PyObject *x)
  Part of the Stable ABI since version 3.10.

  测试一个对象是否为 `True` 单例，与 Python 中的 `x is True` 相同。

  3.10 版新加入.

int `Py_IsFalse`(const PyObject *x)
  Part of the Stable ABI since version 3.10.

  测试一个对象是否为 `False` 单例，与 Python 中的 `x is False` 相同。

  3.10 版新加入.

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()` is changed to the inline static function. Use `Py_SET_REFCNT()` to set an object reference count.

void `Py_SET_REFCNT`(PyObject *o, Py_ssize_t refcnt)

  将对象 o 的引用计数器设为 refcnt。

  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`
  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`

    flags bits indicating how the call should be constructed

  const char *`ml_doc`

    指向文档字符串的内容

The `ml_meth` is a C function pointer. The functions may be of different types, but they always return `PyObject*`. If the function is not of the `PyCFunction`, the compiler will require a cast in the method table. Even though `PyCFunction` defines the first parameter as `PyObject*`, it is common that the method implementation uses the specific C type of the self object.

The `ml_flags` field is a bitfield which can include the following flags. The individual flags indicate either a calling convention or a binding convention.

调用惯例有如下这些:

`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*` 值组成的数组而第三个形参是参数的数量（数组的长度）。

  3.7 版新加入.

  3.10 版更變: `METH_FASTCALL` is now part of the stable ABI.

`METH_FASTCALL | METH_KEYWORDS`

  Extension of `METH_FASTCALL` supporting also keyword arguments, with methods of type `_PyCFunctionFastWithKeywords`. Keyword arguments are passed the same way as in the vectorcall protocol: there is an additional fourth `PyObject*` parameter which is a tuple representing the names of the keyword arguments (which are guaranteed to be strings) or possibly `NULL` if there are no keywords. The values of the keyword arguments are stored in the args array, after the positional arguments.

  3.7 版新加入.

`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`。

`METH_O`

  Methods with a single object argument can be listed with the `METH_O` flag, instead of invoking `PyArg_ParseTuple()` with a `"O"` argument. They have the type `PyCFunction`, with the self parameter, and a `PyObject*` parameter representing the single argument.

这两个常量不是被用来指明调用惯例而是在配合类方法使用时指明绑定。 它们不会被用于在模块上定义的函数。 对于任何给定方法这些旗标最多只会设置其中一个。

`METH_CLASS`

  该方法将接受类型对象而不是类型的实例作为第一个形参。 它会被用于创建 类方法，类似于使用 `classmethod()` 内置函数所创建的结果。

`METH_STATIC`

  该方法将接受 `NULL` 而不是类型的实例作为第一个形参。 它会被用于创建 静态方法，类似于使用 `staticmethod()` 内置函数所创建的结果。

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

`METH_COEXIST`

  该方法将被载入来替代现有的定义。 如果没有 METH_COEXIST，默认将跳过重复的定义。 由于槽位包装器会在方法表之前被载入，例如当存在 sq_contains 槽位时，将会生成一个名为 `__contains__()` 的已包装方法并阻止载入具有相同名称的对应 PyCFunction。 如果定义了此旗标，则 PyCFunction 将被载入来替代此包装器对象并将与槽位共存。 因为对This is helpful because calls to PyCFunctions 的调用比包装器对象调用更为优化所以这是很有帮助的。

## 访问扩展类型的属性

type `PyMemberDef`
  Part of the Stable ABI (including all members).

  描述与某个 C 结构体成员相对应的类型的属性的结构体。 它的字段有:

  域 | C Type | 含意
  --- | --- | ---
  `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 | 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 Type | 含意
  --- | --- | ---
  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` 并设置异常。