# 复数对象

从C API看，Python的复数对象由两个不同的部分实现：一个是在Python程序使用的Python对象，另外的是一个代表真正复数值的C结构体。API提供了函数共同操作两者。

## 表示复数的C结构体

需要注意的是接受这些结构体的作为参数并当做结果返回的函数，都是传递“值”而不是引用指针。此规则适用于整个API。

type Py_complex

  对应于 Python 复数对象的值部分的 C 结构体。 大部分用于处理数据对象的函数都使用该类型的结构体作为相应的输入或输出值。

  double real
  double imag

  其结构定义如下：

      typedef struct {
          double real;
          double imag;
      } Py_complex;

Py_complex _Py_c_sum(Py_complex left, Py_complex right)

  返回两个复数的和，用 C 类型 `Py_complex` 表示。

Py_complex _Py_c_diff(Py_complex left, Py_complex right)

  返回两个复数的差，用 C 类型 `Py_complex` 表示。

Py_complex _Py_c_neg(Py_complex num)

  返回复数 num 的负值，用 C `Py_complex` 表示。

Py_complex _Py_c_prod(Py_complex left, Py_complex right)

  返回两个复数的乘积，用 C 类型 `Py_complex` 表示。

Py_complex _Py_c_quot(Py_complex dividend, Py_complex divisor)

  返回两个复数的商，用 C 类型 `Py_complex` 表示。

  如果 divisor 为空，则此方法将返回零并将 `errno` 设为 `EDOM`。

Py_complex _Py_c_pow(Py_complex num, Py_complex exp)

  返回 num 的 exp 次幂，用 C 类型 `Py_complex` 表示。

  如果 num 为空且 exp 不是正实数，则此方法将返回零并将 `errno` 设为 `EDOM`。

  当溢出时将 `errno` 设为 `ERANGE`。

## 表示复数的Python对象

type PyComplexObject

  这个C类型 `PyObject` 的子类型代表一个 Python 复数对象。

PyTypeObject PyComplex_Type
  属于 稳定 ABI.

  这是个属于 `PyTypeObject` 的代表Python复数类型的实例。在Python层面的类型 `complex` 是同一个对象。

int PyComplex_Check(PyObject *p)

  如果它的参数是一个 `PyComplexObject` 或者 `PyComplexObject` 的子类型则返回真值。 此函数总是会成功执行。

int PyComplex_CheckExact(PyObject *p)

  如果它的参数是一个 `PyComplexObject` 但不是 `PyComplexObject` 的子类型则返回真值。 此函数总是会成功执行。

PyObject *PyComplex_FromCComplex(Py_complex v)
  返回值：新的引用。

  根据一个 C `Py_complex` 值新建 Python 复数对象。 当发生错误时将返回 `NULL` 并设置一个异常。

PyObject *PyComplex_FromDoubles(double real, double imag)
  返回值：新的引用。 属于 稳定 ABI.

  根据 real 和 imag 返回一个新的 `PyComplexObject` 对象。 当发生错误时将返回 `NULL` 并设置一个异常。

double PyComplex_RealAsDouble(PyObject *op)
  属于 稳定 ABI.

  以 C 类型 double 返回 op 的实部。

  如果 op 不是一个 Python 复数对象但是具有 `__complex__()` 方法，则会先调用该方法将 op 转换为 Python 复数对象。 如果未定义 `__complex__()` 则将回退为调用 `PyFloat_AsDouble()` 并返回其结果。

  当失败时，此方法将返回 `-1.0` 并设置一个异常，因此开发者应当调用 `PyErr_Occurred()` 来检查错误。

  在 3.13 版本发生变更: 如果可能将使用 `__complex__()`。

double PyComplex_ImagAsDouble(PyObject *op)
  属于 稳定 ABI.

  以 C 类型 double 返回 op 的虚部。

  如果 op 不是一个 Python 复数对象但是具有 `__complex__()` 方法，则会先调用该方法将 op 转换为 Python 复数对象。 如果未定义 `__complex__()` 则将回退为调用 `PyFloat_AsDouble()` 并在成功时返回 `0.0`。

  当失败时，此方法将返回 `-1.0` 并设置一个异常，因此开发者应当调用 `PyErr_Occurred()` 来检查错误。

  在 3.13 版本发生变更: 如果可能将使用 `__complex__()`。

Py_complex PyComplex_AsCComplex(PyObject *op)

  返回复数 op 的C类型 `Py_complex` 值。

  如果 op 不是一个 Python 复数对象但是具有 `__complex__()` 方法，则会先调用该方法将 op 转换为 Python 复数对象。 如果未定义 `__complex__()` 则将回退至 `__float__()`。 如果未定义 `__float__()` 则将回退至 `__index__()`。

  当失败时，此方法将返回 `Py_complex` 其中 `real` 为 `-1.0` 并设置一个异常，因此开发者应当调用 `PyErr_Occurred()` 来检查错误。

  在 3.8 版本发生变更: 如果可能将使用 `__index__()`。