代码对象
********

代码对象是 CPython 实现的低层级细节。每个代表一块尚未绑定到函数中的可
执行代码。

type PyCodeObject

   用于描述代码对象的对象的 C 结构。此类型字段可随时更改。

PyTypeObject PyCode_Type

   这是一个代表 Python 代码对象 的 "PyTypeObject" 实例。

int PyCode_Check(PyObject *co)

   如果 *co* 是一个 代码对象 则返回真值。此函数总是会成功执行。

Py_ssize_t PyCode_GetNumFree(PyCodeObject *co)

   返回代码对象中 *自由（闭包）变量* 的数量。

int PyUnstable_Code_GetFirstFree(PyCodeObject *co)

   *这是 不稳定 API。它可能在次要版本中不经警告地被更改。*

   返回代码对象中第一个 *自由（闭包）变量* 的位置。

   在 3.13 版本发生变更: 作为 不稳定 C API 的一部分由
   "PyCode_GetFirstFree" 更名而来。 旧名称已被弃用，但在签名再次更改之
   前将保持可用。

PyCodeObject *PyUnstable_Code_New(int argcount, int kwonlyargcount, int nlocals, int stacksize, int flags, PyObject *code, PyObject *consts, PyObject *names, PyObject *varnames, PyObject *freevars, PyObject *cellvars, PyObject *filename, PyObject *name, PyObject *qualname, int firstlineno, PyObject *linetable, PyObject *exceptiontable)

   *这是 不稳定 API。它可能在次要版本中不经警告地被更改。*

   返回一个新的代码对象。如果你需要一个空代码对象来创建帧，请改用
   "PyCode_NewEmpty()"。

   由于字节码的定义经常变化，直接调用 "PyUnstable_Code_New()" 可能会使
   你受限于某个特定的 Python 版本。

   此函数的许多参数以复杂的方式相互依赖，这意味着参数值的细微改变可能
   导致不正确的执行或 VM 崩溃。使用此函数需要极度小心。

   在 3.11 版本发生变更: 添加了 "qualname" 和 "exceptiontable" 形参。

   在 3.12 版本发生变更: 由 "PyCode_New" 更名而来，是 不稳定 C API 的
   一部分。旧名称已被弃用，但在签名再次更改之前仍然可用。

PyCodeObject *PyUnstable_Code_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount, int nlocals, int stacksize, int flags, PyObject *code, PyObject *consts, PyObject *names, PyObject *varnames, PyObject *freevars, PyObject *cellvars, PyObject *filename, PyObject *name, PyObject *qualname, int firstlineno, PyObject *linetable, PyObject *exceptiontable)

   *这是 不稳定 API。它可能在次要版本中不经警告地被更改。*

   与 "PyUnstable_Code_New()" 类似，但额外增加了一个针对仅限位置参数的
   "posonlyargcount"。 适用于 "PyUnstable_Code_New" 的注意事项同样适用
   于这个函数。

   Added in version 3.8: 作为 "PyCode_NewWithPosOnlyArgs"

   在 3.11 版本发生变更: 增加了 "qualname" 和  "exceptiontable" 形参。

   在 3.12 版本发生变更: 重命名为 "PyUnstable_Code_NewWithPosOnlyArgs"
   。旧名称已被弃用，但在签名再次更改之前将保持可用。

PyCodeObject *PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno)
    *返回值：新的引用。*

   返回一个具有指定文件名、函数名和首行行号的空代码对象。结果代码对象
   如果被执行则将引发一个 "Exception"。

int PyCode_Addr2Line(PyCodeObject *co, int byte_offset)

   返回在 "byte_offset" 位置或之前出现且在该位置之后结束的指令的行号。
   如果你只需要一个帧的行号，请改用 "PyFrame_GetLineNumber()" 函数。

   要高效地对代码对象中的行号进行迭代，请使用 **在 PEP 626 中描述的
   API** 规范。

int PyCode_Addr2Location(PyObject *co, int byte_offset, int *start_line, int *start_column, int *end_line, int *end_column)

   将传入的 "int" 指针设为 "byte_offset" 处的指令的源代码行编号和列编
   号。当没有任何特定元素的信息时则将值设为 "0"。

   如果函数执行成功则返回 "1" 否则返回 0。

   Added in version 3.11.

PyObject *PyCode_GetCode(PyCodeObject *co)

   等价于 Python 代码 "getattr(co, 'co_code')"。返回一个指向表示代码对
   象中的字节码的 "PyBytesObject" 的强引用。当出错时，将返回 "NULL" 并
   引发一个异常。

   这个 "PyBytesObject" 可以由解释器按需创建并且不必代表 CPython 所实
   际执行的字节码。 此函数的主要用途是调试器和性能分析工具。

   Added in version 3.11.

PyObject *PyCode_GetVarnames(PyCodeObject *co)

   等价于 Python 代码 "getattr(co, 'co_varnames')"。返回一个指向包含局
   部变量名称的 "PyTupleObject" 的新引用。当出错时，将返回 "NULL" 并引
   发一个异常。

   Added in version 3.11.

PyObject *PyCode_GetCellvars(PyCodeObject *co)

   等价于 Python 代码 "getattr(co, 'co_cellvars')"。返回一个包含被嵌套
   的函数所引用的局部变量名称的 "PyTupleObject" 的新引用。当出错时，将
   返回 "NULL" 并引发一个异常。

   Added in version 3.11.

PyObject *PyCode_GetFreevars(PyCodeObject *co)

   等价于 Python 代码 "getattr(co, 'co_freevars')"。返回一个指向包含 *
   自由（闭包）变量* 名称的 "PyTupleObject" 的新引用。当出错时，将返回
   "NULL" 并引发一个异常。

   Added in version 3.11.

int PyCode_AddWatcher(PyCode_WatchCallback callback)

   注册 *callback* 作为当前解释器的代码对象监视器。返回一个可被传给
   "PyCode_ClearWatcher()" 的 ID。如果出现错误（例如没有足够的可用监视
   器 ID），则返回 "-1" 并设置一个异常。

   Added in version 3.12.

int PyCode_ClearWatcher(int watcher_id)

   清除之前从 "PyCode_AddWatcher()" 返回的当前解释器中由 *watcher_id*
   所标识的监视器。成功时返回 "0"，或者出错时（例如当给定的
   *watcher_id* 未被注册）返回 "-1" 并设置异常。

   Added in version 3.12.

type PyCodeEvent

   由可能的代码对象监视器事件组成的枚举："PY_CODE_EVENT_CREATE"、
   "PY_CODE_EVENT_DESTROY"

   Added in version 3.12.

typedef int (*PyCode_WatchCallback)(PyCodeEvent event, PyCodeObject *co)

   代码对象监视器回调函数的类型。

   如果 *event* 为 "PY_CODE_EVENT_CREATE"，则回调会在 *co* 完全初始化
   之后被唤起。在其他情况下，回调会在 *co* 的销毁执行之前被唤起，因此
   可以检查 *co* 在之前的状态。

   如果 *event* 为 "PY_CODE_EVENT_DESTROY"，则在回调中接受一个即将被销
   毁的代码对象的引用将使其重生，并阻止其在此时被释放。 当重生的对象以
   后再被销毁时，任何在当时已激活的监视器回调将再次被调用。

   本 API 的用户不应依赖内部运行时的实现细节。这类细节可能包括但不限于
   创建和销毁代码对象的确切顺序和时间。虽然这些细节的变化可能会导致监
   视器可观察到的差异（包括回调是否被唤起），但不会改变正在执行的
   Python 代码的语义。

   如果该回调设置了一个异常，则它必须返回 "-1"；此异常将作为不可引发的
   异常使用 "PyErr_WriteUnraisable()" 打印出来。在其他情况下它应当返回
   "0"。

   在进入回调时可能已经设置了尚未处理的异常。在此情况下，回调应当返回
   "0" 并仍然设置同样的异常。这意味着该回调不可调用任何其他可设置异常
   的 API，除非它先保存并清空异常状态，并在返回之前恢复它。

   Added in version 3.12.

PyObject *PyCode_Optimize(PyObject *code, PyObject *consts, PyObject *names, PyObject *lnotab_obj)

   此函数已处于 *soft deprecated* 状态并不做任何事。

   在 Python 3.10 之前，此函数将对代码对象执行基本的优化。

   在 3.10 版本发生变更: 此函数现在不执行任何操作。


代码对象标志
************

代码对象包含一个标志位字段，可以通过 "co_flags" Python 属性检索（例如
使用 "PyObject_GetAttrString()"），并通过 *flags* 参数设置
"PyUnstable_Code_New()" 及类似函数。

以 "CO_FUTURE_" 开头的标志名称对应于通常可通过 未来语句 选择的功能。这
些标志可以在 "PyCompilerFlags.cf_flags" 中使用。请注意，许多
"CO_FUTURE_" 标志在当前版本的 Python 中是强制性的，设置它们没有效果。

以下是可用的标志位。有关其具体含义，请参阅对应 Python 原生标志位的官方
文档说明。

+----------------------------------------------------+----------------------------------------------------+
| 标志位                                             | 含义                                               |
|====================================================|====================================================|
| CO_OPTIMIZED                                       | "inspect.CO_OPTIMIZED"                             |
+----------------------------------------------------+----------------------------------------------------+
| CO_NEWLOCALS                                       | "inspect.CO_NEWLOCALS"                             |
+----------------------------------------------------+----------------------------------------------------+
| CO_VARARGS                                         | "inspect.CO_VARARGS"                               |
+----------------------------------------------------+----------------------------------------------------+
| CO_VARKEYWORDS                                     | "inspect.CO_VARKEYWORDS"                           |
+----------------------------------------------------+----------------------------------------------------+
| CO_NESTED                                          | "inspect.CO_NESTED"                                |
+----------------------------------------------------+----------------------------------------------------+
| CO_GENERATOR                                       | "inspect.CO_GENERATOR"                             |
+----------------------------------------------------+----------------------------------------------------+
| CO_COROUTINE                                       | "inspect.CO_COROUTINE"                             |
+----------------------------------------------------+----------------------------------------------------+
| CO_ITERABLE_COROUTINE                              | "inspect.CO_ITERABLE_COROUTINE"                    |
+----------------------------------------------------+----------------------------------------------------+
| CO_ASYNC_GENERATOR                                 | "inspect.CO_ASYNC_GENERATOR"                       |
+----------------------------------------------------+----------------------------------------------------+
| CO_HAS_DOCSTRING                                   | "inspect.CO_HAS_DOCSTRING"                         |
+----------------------------------------------------+----------------------------------------------------+
| CO_METHOD                                          | "inspect.CO_METHOD"                                |
+----------------------------------------------------+----------------------------------------------------+
| CO_FUTURE_DIVISION                                 | 无效果 ("__future__.division")                     |
+----------------------------------------------------+----------------------------------------------------+
| CO_FUTURE_ABSOLUTE_IMPORT                          | 无效果 ("__future__.absolute_import")              |
+----------------------------------------------------+----------------------------------------------------+
| CO_FUTURE_WITH_STATEMENT                           | 无效果 ("__future__.with_statement")               |
+----------------------------------------------------+----------------------------------------------------+
| CO_FUTURE_PRINT_FUNCTION                           | 无效果 ("__future__.print_function")               |
+----------------------------------------------------+----------------------------------------------------+
| CO_FUTURE_UNICODE_LITERALS                         | 无效果 ("__future__.unicode_literals")             |
+----------------------------------------------------+----------------------------------------------------+
| CO_FUTURE_GENERATOR_STOP                           | 无效果 ("__future__.generator_stop")               |
+----------------------------------------------------+----------------------------------------------------+
| CO_FUTURE_ANNOTATIONS                              | "__future__.annotations"                           |
+----------------------------------------------------+----------------------------------------------------+


附加信息
********

为了支持对帧求值的低层级扩展，如外部即时编译器等，可以在代码对象上附加
任意的额外数据。

这些函数是不稳定 C API 层的一部分：该功能是 CPython 的实现细节，此 API
可能随时改变而不发出弃用警告。

Py_ssize_t PyUnstable_Eval_RequestCodeExtraIndex(freefunc free)

   *这是 不稳定 API。它可能在次要版本中不经警告地被更改。*

   返回一个新的不透明索引值用于向代码对象添加数据。

   通常情况下（对于每个解释器）你只需调用该函数一次然后将调用结果与
   "PyCode_GetExtra" 和 "PyCode_SetExtra" 一起使用以操作单个代码对象上
   的数据。

   如果 *free* 不为 "NULL": 当代码对象被释放时，*free* 将在存储于新索
   引下的非 "NULL" 数据上被调用。当存储 "PyObject" 时使用
   "Py_DecRef()"。

   Added in version 3.6: 作为 "_PyEval_RequestCodeExtraIndex"

   在 3.12 版本发生变更: 重命名为
   "PyUnstable_Eval_RequestCodeExtraIndex"。旧的私有名称已被弃用，但在
   API 更改之前仍将可用。

int PyUnstable_Code_GetExtra(PyObject *code, Py_ssize_t index, void **extra)

   *这是 不稳定 API。它可能在次要版本中不经警告地被更改。*

   将 *extra* 设为存储在给定索引下的额外数据。成功时将返回 0。失败时将
   设置一个异常并返回 -1。

   如果未在索引下设置数据，则将 *extra* 设为 "NULL" 并返回 0 而不设置
   异常。

   Added in version 3.6: 作为 "_PyCode_GetExtra"

   在 3.12 版本发生变更: 重命名为 "PyUnstable_Code_GetExtra"。旧的私有
   名称已被弃用，但在 API 更改之前仍将可用。

int PyUnstable_Code_SetExtra(PyObject *code, Py_ssize_t index, void *extra)

   *这是 不稳定 API。它可能在次要版本中不经警告地被更改。*

   将存储在给定索引下的额外数据设为 *extra*。成功时将返回 0。失败时将
   设置一个异常并返回 -1。

   Added in version 3.6: 作为 "_PyCode_SetExtra"

   在 3.12 版本发生变更: 重命名为 "PyUnstable_Code_SetExtra"。旧的私有
   名称已被弃用，但在 API 更改之前仍将可用。
