"inspect" --- 检查活动对象
**************************

**源代码:** Lib/inspect.py

======================================================================

The "inspect" module provides several useful functions to help get
information about live objects such as modules, classes, methods,
functions, tracebacks, frame objects, and code objects.  For example,
it can help you examine the contents of a class, retrieve the source
code of a method, extract and format the argument list for a function,
or get all the information you need to display a detailed traceback.

该模块提供了4种主要的功能：类型检查、获取源代码、检查类与函数、检查解
释器的调用堆栈。


类型和成员
==========

"getmembers()" 函数获取对象如类或模块的成员。 名称以“is”打头的函数主要
是作为传给 "getmembers()" 的第二个参数的便捷选项提供的。 它们还可帮助
你确定你是否能找到下列特殊属性（请参阅 模块对象上与导入相关的属性 了解
有关模块属性的详情）:

+-------------------+---------------------+-----------------------------+
| 类型              | 属性                | 描述                        |
|===================|=====================|=============================|
| class -- 类       | __doc__             | 文档字符串                  |
+-------------------+---------------------+-----------------------------+
|                   | __name__            | 类定义时所使用的名称        |
+-------------------+---------------------+-----------------------------+
|                   | __qualname__        | qualified name -- 限定名称  |
+-------------------+---------------------+-----------------------------+
|                   | __module__          | 该类型被定义时所在的模块的  |
|                   |                     | 名称                        |
+-------------------+---------------------+-----------------------------+
|                   | __type_params__     | 一个包含泛型类的 类型形参   |
|                   |                     | 的元组                      |
+-------------------+---------------------+-----------------------------+
| method -- 方法    | __doc__             | 文档字符串                  |
+-------------------+---------------------+-----------------------------+
|                   | __name__            | 该方法定义时所使用的名称    |
+-------------------+---------------------+-----------------------------+
|                   | __qualname__        | qualified name -- 限定名称  |
+-------------------+---------------------+-----------------------------+
|                   | __func__            | 实现该方法的函数对象        |
+-------------------+---------------------+-----------------------------+
|                   | __self__            | 该方法被绑定的实例，若没有  |
|                   |                     | 绑定则为 "None"             |
+-------------------+---------------------+-----------------------------+
|                   | __module__          | 定义此方法的模块的名称      |
+-------------------+---------------------+-----------------------------+
| function -- 函数  | __doc__             | 文档字符串                  |
+-------------------+---------------------+-----------------------------+
|                   | __name__            | 用于定义此函数的名称        |
+-------------------+---------------------+-----------------------------+
|                   | __qualname__        | qualified name -- 限定名称  |
+-------------------+---------------------+-----------------------------+
|                   | __code__            | 包含已编译函数的代码对象    |
|                   |                     | *bytecode*                  |
+-------------------+---------------------+-----------------------------+
|                   | __defaults__        | 所有位置或关键字参数的默认  |
|                   |                     | 值的元组                    |
+-------------------+---------------------+-----------------------------+
|                   | __kwdefaults__      | 保存仅关键字参数的所有默认  |
|                   |                     | 值的映射                    |
+-------------------+---------------------+-----------------------------+
|                   | __globals__         | 此函数定义所在的全局命名空  |
|                   |                     | 间                          |
+-------------------+---------------------+-----------------------------+
|                   | __builtins__        | builtins 命名空间           |
+-------------------+---------------------+-----------------------------+
|                   | __annotations__     | 参数名称到注解的映射；保留  |
|                   |                     | 键 ""return"" 用于返回值注  |
|                   |                     | 解。                        |
+-------------------+---------------------+-----------------------------+
|                   | __type_params__     | 一个包含泛型函数的 类型形参 |
|                   |                     | 的元组                      |
+-------------------+---------------------+-----------------------------+
|                   | __module__          | 此函数定义所在的模块名称    |
+-------------------+---------------------+-----------------------------+
| traceback -- 回溯 | tb_frame            | 此层的帧对象                |
+-------------------+---------------------+-----------------------------+
|                   | tb_lasti            | 在字节码中最后尝试的指令的  |
|                   |                     | 索引                        |
+-------------------+---------------------+-----------------------------+
|                   | tb_lineno           | 当前行在 Python 源代码中的  |
|                   |                     | 行号                        |
+-------------------+---------------------+-----------------------------+
|                   | tb_next             | 下一个内部回溯对象（由本层  |
|                   |                     | 调用）                      |
+-------------------+---------------------+-----------------------------+
| frame -- 帧       | f_back              | 下一个外部帧对象（此帧的调  |
|                   |                     | 用者）                      |
+-------------------+---------------------+-----------------------------+
|                   | f_builtins          | 此帧执行时所在的 builtins   |
|                   |                     | 命名空间                    |
+-------------------+---------------------+-----------------------------+
|                   | f_code              | 在此帧中执行的代码对象      |
+-------------------+---------------------+-----------------------------+
|                   | f_globals           | 此帧执行时所在的全局命名空  |
|                   |                     | 间                          |
+-------------------+---------------------+-----------------------------+
|                   | f_lasti             | 在字节码中最后尝试的指令的  |
|                   |                     | 索引                        |
+-------------------+---------------------+-----------------------------+
|                   | f_lineno            | 当前行在 Python 源代码中的  |
|                   |                     | 行号                        |
+-------------------+---------------------+-----------------------------+
|                   | f_locals            | 此帧所看到的局部命名空间    |
+-------------------+---------------------+-----------------------------+
|                   | f_generator         | 返回拥有该帧的生成器或协程  |
|                   |                     | ，或者如果该帧是属于常规函  |
|                   |                     | 数则返回 "None"             |
+-------------------+---------------------+-----------------------------+
|                   | f_trace             | 此帧的追踪函数，或 "None"   |
+-------------------+---------------------+-----------------------------+
|                   | f_trace_lines       | 指明一个追踪事件是否针对每  |
|                   |                     | 个源代码行触发              |
+-------------------+---------------------+-----------------------------+
|                   | f_trace_opcodes     | 指示是否请求每个操作码事件  |
+-------------------+---------------------+-----------------------------+
|                   | clear()             | 用于清除对局部变量的所有引  |
|                   |                     | 用                          |
+-------------------+---------------------+-----------------------------+
| code -- 代码      | co_argcount         | 参数数量（不包括仅关键字参  |
|                   |                     | 数、* 或 ** 参数）          |
+-------------------+---------------------+-----------------------------+
|                   | co_code             | 字符串形式的原始字节码      |
+-------------------+---------------------+-----------------------------+
|                   | co_cellvars         | 单元变量名称的元组(通过包含 |
|                   |                     | 作用域引用)                 |
+-------------------+---------------------+-----------------------------+
|                   | co_consts           | 字节码中使用的常量元组      |
+-------------------+---------------------+-----------------------------+
|                   | co_filename         | 创建此代码对象的文件的名称  |
+-------------------+---------------------+-----------------------------+
|                   | co_firstlineno      | Python 源代码中第一行的行号 |
+-------------------+---------------------+-----------------------------+
|                   | co_flags            | "CO_*" 标志的位图，详见 此  |
|                   |                     | 处                          |
+-------------------+---------------------+-----------------------------+
|                   | co_lnotab           | 编码的行号到字节码索引的映  |
|                   |                     | 射                          |
+-------------------+---------------------+-----------------------------+
|                   | co_freevars         | 自由变量的名字组成的元组（  |
|                   |                     | 通过函数闭包引用）          |
+-------------------+---------------------+-----------------------------+
|                   | co_posonlyargcount  | 仅限位置参数的数量          |
+-------------------+---------------------+-----------------------------+
|                   | co_kwonlyargcount   | 仅限关键字参数的数量（不包  |
|                   |                     | 括 ** 参数）                |
+-------------------+---------------------+-----------------------------+
|                   | co_name             | 定义此代码对象的名称        |
+-------------------+---------------------+-----------------------------+
|                   | co_qualname         | 定义此代码对象的完整限定名  |
|                   |                     | 称                          |
+-------------------+---------------------+-----------------------------+
|                   | co_names            | 除参数和函数局部变量之外的  |
|                   |                     | 名称元组                    |
+-------------------+---------------------+-----------------------------+
|                   | co_nlocals          | 局部变量的数量              |
+-------------------+---------------------+-----------------------------+
|                   | co_stacksize        | 所需的虚拟机栈空间          |
+-------------------+---------------------+-----------------------------+
|                   | co_varnames         | 参数名和局部变量的元组      |
+-------------------+---------------------+-----------------------------+
|                   | co_lines()          | 返回产生连续字节码范围的迭  |
|                   |                     | 代器                        |
+-------------------+---------------------+-----------------------------+
|                   | co_positions()      | 返回每个字节码指令的源代码  |
|                   |                     | 位置的迭代器                |
+-------------------+---------------------+-----------------------------+
|                   | replace()           | 返回具有新值的代码对象的副  |
|                   |                     | 本                          |
+-------------------+---------------------+-----------------------------+
| generator -- 生成 | __name__            | 名称                        |
| 器                |                     |                             |
+-------------------+---------------------+-----------------------------+
|                   | __qualname__        | qualified name -- 限定名称  |
+-------------------+---------------------+-----------------------------+
|                   | gi_frame            | frame -- 帧                 |
+-------------------+---------------------+-----------------------------+
|                   | gi_running          | 生成器在运行吗？            |
+-------------------+---------------------+-----------------------------+
|                   | gi_suspended        | 生成器暂停了吗？            |
+-------------------+---------------------+-----------------------------+
|                   | gi_code             | code -- 代码                |
+-------------------+---------------------+-----------------------------+
|                   | gi_yieldfrom        | 通过 "yield from" 迭代的对  |
|                   |                     | 象，或 "None"               |
+-------------------+---------------------+-----------------------------+
| 异步生成器        | __name__            | 名称                        |
+-------------------+---------------------+-----------------------------+
|                   | __qualname__        | qualified name -- 限定名称  |
+-------------------+---------------------+-----------------------------+
|                   | ag_await            | 正在等待的对象，或 "None"   |
+-------------------+---------------------+-----------------------------+
|                   | ag_frame            | frame -- 帧                 |
+-------------------+---------------------+-----------------------------+
|                   | ag_running          | 生成器在运行吗？            |
+-------------------+---------------------+-----------------------------+
|                   | ag_suspended        | 生成器暂停了吗？            |
+-------------------+---------------------+-----------------------------+
|                   | ag_code             | code -- 代码                |
+-------------------+---------------------+-----------------------------+
| coroutine -- 协程 | __name__            | 名称                        |
+-------------------+---------------------+-----------------------------+
|                   | __qualname__        | qualified name -- 限定名称  |
+-------------------+---------------------+-----------------------------+
|                   | cr_await            | 正在等待的对象，或 "None"   |
+-------------------+---------------------+-----------------------------+
|                   | cr_frame            | frame -- 帧                 |
+-------------------+---------------------+-----------------------------+
|                   | cr_running          | 这个协程正在运行吗？        |
+-------------------+---------------------+-----------------------------+
|                   | cr_suspended        | 这个协程被挂起了吗？        |
+-------------------+---------------------+-----------------------------+
|                   | cr_code             | code -- 代码                |
+-------------------+---------------------+-----------------------------+
|                   | cr_origin           | 协程被创建的位置，或 "None" |
|                   |                     | 。参见 "sys.set_coroutine_  |
|                   |                     | origin_tracking_depth()"    |
+-------------------+---------------------+-----------------------------+
| builtin           | __doc__             | 文档字符串                  |
+-------------------+---------------------+-----------------------------+
|                   | __name__            | 此函数或方法的原始名称      |
+-------------------+---------------------+-----------------------------+
|                   | __qualname__        | qualified name -- 限定名称  |
+-------------------+---------------------+-----------------------------+
|                   | __self__            | 方法绑定到的实例，或 "None" |
+-------------------+---------------------+-----------------------------+

在 3.5 版本发生变更: 为生成器添加 "__qualname__" 和 "gi_yieldfrom" 属
性。生成器的 "__name__" 属性现在由函数名称设置，而不是代码对象名称，并
且现在可以被修改。

在 3.7 版本发生变更: 为协程添加 "cr_origin" 属性。

在 3.10 版本发生变更: 为函数添加 "__builtins__" 属性。

在 3.11 版本发生变更: 为生成器添加 "gi_suspended" 属性。

在 3.11 版本发生变更: 为协程添加 "cr_suspended" 属性。

在 3.12 版本发生变更: 为异步生成器添加 "ag_suspended" 属性。

在 3.14 版本发生变更: 为帧添加 "f_generator" 属性。

inspect.getmembers(object[, predicate])

   返回一个对象上的所有成员，组成以 "(名称, 值)" 对为元素的列表，按名
   称排序。如果提供了可选的 *predicate* 参数（会对每个成员的 "值" 对象
   进行一次调用），则仅包含该断言为真的成员。

   备注:

     当参数是一个类且这些属性在元类的自定义方法 "__dir__()" 中列出时
     "getmembers()" 将只返回在元类中定义的类属性。

inspect.getmembers_static(object[, predicate])

   将一个对象的所有成员作为由 "(name, value)" 对组成并按名称排序的列表
   返回而不触发通过描述器协议 __getattr__ 或 __getattribute__ 执行的动
   态查找。 或是作为可选项，只返回满足给定条件的成员。

   备注:

     "getmembers_static()" 可能无法获得 getmembers 所能获取的所有成员
     （如动态创建的属性）并且可能会找到一些 getmembers 所不能找到的成
     员（如会引发 AttributeError 的描述器）。 在某些情况下它还能返回描
     述器对象而不是实例成员。

   Added in version 3.11.

inspect.getmodulename(path)

   返回由文件名 *path* 表示的模块名字，但不包括外层的包名。文件扩展名
   会检查是否在 "importlib.machinery.all_suffixes()" 列出的条目中。如
   果符合，则文件路径的最后一个组成部分会去掉后缀名后被返回；否则返回
   "None"。

   值得注意的是，这个函数 *仅* 返回可以作为 Python 模块的名字，而有可
   能指向一个 Python 包的路径仍然会返回 "None"。

   在 3.3 版本发生变更: 该函数直接基于 "importlib"。

inspect.ismodule(object)

   当该对象是一个模块时返回 "True"。

inspect.isclass(object)

   当该对象是一个类时返回 "True"，无论是内置类或者 Python 代码中定义的
   类。

   This function returns "False" for generic aliases of classes, such
   as "list[int]".

inspect.ismethod(object)

   当该对象是一个 Python 写成的绑定方法时返回 "True"。

   备注:

     For example, given this class:

        >>> class Greeter:
        ...     def say_hello(self):
        ...         print('hello!')

     A bound method (also known as an *instance method*) is created
     when accessing "say_hello" (a *function* defined in the "Greeter"
     namespace) through an instance of the "Greeter" class:

        >>> instance = Greeter()

        >>> instance.say_hello
        <bound method Greeter.say_hello of <__main__.Greeter object ...>>
        >>> ismethod(instance.say_hello)
        True
        >>> isfunction(instance.say_hello)
        False

     Accessing "say_hello" through the "Greeter" class will return the
     function itself. For this function, "ismethod()" will return
     "False", but "isfunction()" will return "True":

        >>> Greeter.say_hello
        <function Greeter.say_hello at 0x7f7503854a90>
        >>> ismethod(Greeter.say_hello)
        False
        >>> isfunction(Greeter.say_hello)
        True

     See 方法 for details.

inspect.isfunction(object)

   当该对象是一个 Python 函数时（包括使用 *lambda* 表达式创造的函数）
   ，返回 "True"。

   See the note for "ismethod()" for an example.

inspect.ispackage(object)

   如果该对象是一个 *package* 则返回 "True"。

   Added in version 3.14.

inspect.isgeneratorfunction(object)

   当该对象是一个 Python 生成器函数时返回 "True"。

   It also returns "True" for bound methods created from Python
   generator functions (see 方法 for more information).

   在 3.8 版本发生变更: 对于使用 "functools.partial()" 封装的函数，如
   果被封装的函数是一个 Python 生成器函数，现在也会返回 "True"。

   在 3.13 版本发生变更: 现在对于使用 "functools.partialmethod()" 包装
   的函数，如果被包装的函数是一个 Python 生成器函数则返回 "True"。

inspect.isgenerator(object)

   当该对象是一个生成器时返回 "True"。

inspect.iscoroutinefunction(object)

   如果该对象为 *coroutine function* (使用 "async def" 语法定义的函数
   ), 包装了 *coroutine function* 的 "functools.partial()" 或使用
   "markcoroutinefunction()" 标记的同步函数则返回 "True"。

   Added in version 3.5.

   在 3.8 版本发生变更: 对于使用 "functools.partial()" 封装的函数，如
   果被封装的函数是一个 *协程函数* ，现在也会返回 "True"。

   在 3.12 版本发生变更: 使用 "markcoroutinefunction()" 标记的同步函数
   现在将返回 "True"。

   在 3.13 版本发生变更: 现在对于使用 "functools.partialmethod()" 包装
   的函数，如果被包装的函数是一个 *coroutine function* 则返回 "True"。

inspect.markcoroutinefunction(func)

   将一个可调用对象标记为 *coroutine function* 的装饰器，如果它不会被
   "iscoroutinefunction()" 检测到的话。

   这可被用于返回 *coroutine* 的同步函数，如果该函数被传给需要
   "iscoroutinefunction()" 的 API 的话。

   在可能的情况下，更推荐使用 "async def" 函数。 调用该函数并使用
   "iscoroutine()" 来检测其返回值也是可接受的。

   Added in version 3.12.

inspect.iscoroutine(object)

   当该对象是一个由 "async def" 函数创建的 *协程* 时返回 "True"。

   Added in version 3.5.

inspect.isawaitable(object)

   如果该对象可以在 "await" 表达式中使用时返回 "True"。

   也可被用于区分基于生成器的协程和常规的生成器：

      import types

      def gen():
          yield
      @types.coroutine
      def gen_coro():
          yield

      assert not isawaitable(gen())
      assert isawaitable(gen_coro())

   Added in version 3.5.

inspect.isasyncgenfunction(object)

   如果对象是一个 *asynchronous generator* 函数则返回 "True"，例如：

      >>> async def agen():
      ...     yield 1
      ...
      >>> inspect.isasyncgenfunction(agen)
      True

   Added in version 3.6.

   在 3.8 版本发生变更: 对于使用 "functools.partial()" 封装的函数，如
   果被封装的函数是一个 *异步生成器* 函数现在也会返回 "True"。

   在 3.13 版本发生变更: 使用 "functools.partialmethod()" 包装的函数现
   在如果被包装的函数是一个 *asynchronous generator* 函数则会返回
   "True"。

inspect.isasyncgen(object)

   如果该对象是一个由 *异步生成器* 函数创建的 *异步生成器迭代器*，则返
   回 "True"。

   Added in version 3.6.

inspect.istraceback(object)

   如果该对象是一个回溯则返回 "True"。

inspect.isframe(object)

   如果该对象是一个帧对象则返回 "True"。

inspect.iscode(object)

   如果该对象是一个代码对象则返回 "True"。

inspect.isbuiltin(object)

   如果该对象是一个内置函数或一个绑定的内置方法，则返回 "True"。

inspect.ismethodwrapper(object)

   如果对象类型为 "MethodWrapperType" 则返回 "True"。

   这些是 "MethodWrapperType" 的实例，如 "__str__()", "__eq__()" 和
   "__repr__()"。

   Added in version 3.11.

inspect.isroutine(object)

   如果该对象是一个用户定义的或内置的函数或者方法，则返回 "True"。

inspect.isabstract(object)

   如果该对象是一个抽象基类则返回 "True"。

inspect.ismethoddescriptor(object)

   如果该对象是一个方法描述器，但 "ismethod()" 、 "isclass()" 、
   "isfunction()" 及 "isbuiltin()" 均不为真，则返回 "True"。

   例如，该函数对于 "int.__add__" 为真值。 一个通过此测试的对象会有
   "__get__()" 方法，但没有 "__set__()" 方法或 "__delete__()" 方法。
   除此以外，属性集合是可变的。 一个 "__name__" 属性通常是合理的，而
   "__doc__" 通常也是如此。

   以描述器实现的能够通过其他某个测试的函数对于 "ismethoddescriptor()"
   测试也会返回 "False"，这只是因为其他测试提供了更多保证 —— 比如，当
   一个对象通过 "ismethod()" 时你将能够使用 "__func__" 等属性。

   在 3.13 版本发生变更: 此函数将不再错误地将具有 "__get__()" 和
   "__delete__()"，但没有 "__set__()" 的对象报告为方法描述器（这样的对
   象是数据描述器，不是方法描述器）。

inspect.isdatadescriptor(object)

   如果该对象是一个数据描述器则返回 "True"。

   数据描述器具有 "__set__" 或 "__delete__" 方法。 例如特征属性（在
   Python 中定义）、getset 和成员等。 后两者是在 C 中定义并且有针对这
   些类型的更具体的测试，它们在不同 Python 实现中均能保持健壮性。 通常
   ，数据描述器还具有 "__name__" 和 "__doc__" 属性（特征属性、getset
   和成员都同时具有这些属性），但并不保证这一点。

inspect.isgetsetdescriptor(object)

   如果该对象是一个 getset 描述器则返回 "True"。

   getset 是在扩展模块中通过 "PyGetSetDef" 结构体定义的属性。对于不包
   含这种类型的 Python 实现，这个方法将永远返回 "False"。

inspect.ismemberdescriptor(object)

   如果该对象是一个成员描述器则返回 "True"。

   成员描述器是在扩展模块中通过 "PyMemberDef" 结构体定义的属性。对于不
   包含这种类型的 Python 实现，这个方法将永远返回 "False"。


获取源代码
==========

inspect.getdoc(object)

   获取对象的文档字符串并通过 "cleandoc()" 进行清理。如果对象本身并未
   提供文档字符串并且这个对象是一个类、一个方法、一个特性或者一个描述
   器，将通过继承层次结构获取文档字符串。如果文档字符串无效或缺失，则
   返回 "None"。

   在 3.5 版本发生变更: 文档字符串没有被重写的话现在会被继承。

inspect.getcomments(object)

   任意多行注释作为单一一个字符串返回。对于类、函数和方法，选取紧贴在
   该对象的源代码之前的注释；对于模块，选取 Python 源文件顶部的注释。
   如果对象的源代码不可获得，返回 "None"。这可能是因为对象是 C 语言中
   或者是在交互式命令行中定义的。

inspect.getfile(object)

   返回定义了这个对象的文件名（包括文本文件或二进制文件）。如果该对象
   是一个内置模块、类或函数则会失败并引发一个 "TypeError"。

inspect.getmodule(object)

   尝试猜测一个对象是在哪个模块中定义的。 如果无法确定模块则返回
   "None"。

inspect.getsourcefile(object)

   返回一个对象定义所在 Python 源文件的名称，如果无法获取源文件则返回
   "None"。 如果对象是一个内置模块、类或函数则将失败并引发 "TypeError"
   。

inspect.getsourcelines(object)

   返回一个源代码行的列表和对象的起始行号。 参数可以是一个模块、类、方
   法、函数、回溯或者代码对象。 源代码将以与该对象所对应的行的列表的形
   式返回并且行号指明其中第一行代码出现在初始源文件的那个位置。 如果源
   代码无法被获取则会引发 "OSError"。 如果对象是一个内置模块、类或函数
   则会引发 "TypeError"。

   在 3.3 版本发生变更: 现在会引发 "OSError" 而不是 "IOError"，后者现
   在是前者的一个别名。

inspect.getsource(object)

   返回对象的源代码文本。 参数可以是一个模块、类、方法、函数、回溯帧或
   代码对象。 源代码将以单个字符串的形式被返回。 如果源代码无法被获取
   则会引发 "OSError"。 如果对象是一个内置模块、类或函数则会引发
   "TypeError"。

   在 3.3 版本发生变更: 现在会引发 "OSError" 而不是 "IOError"，后者现
   在是前者的一个别名。

inspect.cleandoc(doc)

   清理文档字符串中为对齐当前代码块进行的缩进

   第一行的所有前缀空白符会被移除。从第二行开始所有可以被统一去除的空
   白符也会被去除。之后，首尾的空白行也会被移除。同时，所有制表符会被
   展开到空格。


使用 Signature 对象对可调用对象进行内省
=======================================

Added in version 3.3.

"Signature" 对象代表一个可调用对象的调用签名及其返回值标注。 要获取一
个 "Signature" 对象，可使用 "signature()" 函数。

inspect.signature(callable, *, follow_wrapped=True, globals=None, locals=None, eval_str=False, annotation_format=Format.VALUE)

   返回一个给定 *callable* 的 "Signature" 对象：

      >>> from inspect import signature
      >>> def foo(a, *, b:int, **kwargs):
      ...     pass

      >>> sig = signature(foo)

      >>> str(sig)
      '(a, *, b: int, **kwargs)'

      >>> str(sig.parameters['b'])
      'b: int'

      >>> sig.parameters['b'].annotation
      <class 'int'>

   接受各类的 Python 可调用对象，包括单纯的函数、类，到
   "functools.partial()" 对象。

   如果某些注解是字符串 (例如，因为使用了 "from __future__ import
   annotations")，"signature()" 将尝试使用
   "annotationlib.get_annotations()" 自动反字符串化该注解。 解析注解时
   ，将 *globals*、*locals* 和 *eval_str* 形参传递给
   "annotationlib.get_annotations()"；有关如何使用这些参数的说明，请参
   阅 "annotationlib.get_annotations()" 的文档。可以将
   "annotationlib.Format" 枚举的成员传递给 *annotation_format* 形参，
   以控制返回的注解的格式。 例如，使用
   "annotation_format=annotationlib.Format.STRING" 以字符串格式返回注
   解。

   如果没有可提供的签名则会引发 "ValueError"，而如果对象类型不受支持则
   会引发 "TypeError"。 同时，如果注解被字符串化，并且 *eval_str* 不为
   假值，则在 "annotationlib.get_annotations()" 中调用 "eval()" 来反字
   符串化注解可能会引发任何种类的异常。

   函数签名中的斜杠（/）表示在它之前的形参是仅限位置的。参阅 有关仅限
   位置形参的 FAQ 条目。

   在 3.5 版本发生变更: 添加了 *follow_wrapped* 形参。 传入 "False" 以
   获得特定 *callable* 的签名 ("callable.__wrapped__" 将不会被用来解包
   被装饰的可调用对象。)

   在 3.10 版本发生变更: 添加了 *globals*, *locals* 和 *eval_str* 形参
   。

   在 3.14 版本发生变更: 增加了 *annotation_format* 形参。

   备注:

     一些可调用对象可能在特定 Python 实现中无法被内省。例如，在
     CPython 中，部分通过 C 语言定义的内置函数不提供关于其参数的元数据
     。

   如果传递的对象有一个 "__signature__" 属性，我们可以用它来创建签名。
   确切的语义是实现细节，可能会有未经宣布的更改。有关当前语义，请查阅
   源代码。

class inspect.Signature(parameters=None, *, return_annotation=Signature.empty)

   "Signature" 对象表示一个函数的调用签名及其返回值标注。 对于函数所接
   受的每个形参它会在其 "parameters" 多项集中存储一个 "Parameter" 对象
   。

   可选参数 *parameters* 是一个 "Parameter" 对象组成的序列，它会在之后
   被验证不存在名字重复的参数，并且参数处于正确的顺序，即仅限位置参数
   最前，之后紧接着可位置可关键字参数，并且有默认值参数在无默认值参数
   之后。

   可选的 *return_annotation* 参数可以是任意 Python 对象。 它表示可调
   用对象的 "return" 标注。

   "Signature" 对象是 *不可变* 对象。 使用 "Signature.replace()" 或
   "copy.replace()" 来创建经修改的副本。

   在 3.5 版本发生变更: "Signature" 对象现在是可 pickle 且 *hashable*
   的对象。

   empty

      该类的一个特殊标记来明确指出返回值标注缺失。

   parameters

      一个参数名字到对应 "Parameter" 对象的有序映射。参数以严格的定义
      顺序出现，包括仅关键字参数。

      在 3.7 版本发生变更: Python 从 3.7 版起才显式地保证了它保持仅关
      键字参数的定义顺序，尽管实践上在 Python 3 中一直保持了这个顺序。

   return_annotation

      可调用对象的“返回值”标注。如果可调用对象没有“返回值”标注，这个属
      性会被设置为 "Signature.empty"。

   bind(*args, **kwargs)

      构造一个位置和关键字实参到形参的映射。如果 "*args" 和 "**kwargs"
      符合签名，则返回一个 "BoundArguments"；否则引发一个 "TypeError"
      。

   bind_partial(*args, **kwargs)

      与 "Signature.bind()" 作用方式相同，但允许省略部分必要的参数（模
      仿 "functools.partial()" 的行为）。返回 "BoundArguments"，或者在
      传入参数不符合签名的情况下，引发一个 "TypeError"。

   replace(*[, parameters][, return_annotation])

      根据调用 "replace()" 的实例新建一个 "Signature" 实例。 可以通过
      传入不同的 *parameters* 和/或 *return_annotation* 来覆盖基类签名
      的相应特征属性。 要从拷贝的 "Signature" 中移除
      "return_annotation"，可以传入 "Signature.empty"。

         >>> def test(a, b):
         ...     pass
         ...
         >>> sig = signature(test)
         >>> new_sig = sig.replace(return_annotation="new return anno")
         >>> str(new_sig)
         "(a, b) -> 'new return anno'"

      "Signature" 对象也被泛型函数 "copy.replace()" 所支持。

   format(*, max_width=None, quote_annotation_strings=True)

      创建一个 "Signature" 对象的字符串表示形式。

      如果传入了 *max_width*，该方法将尝试将签名调整为每行至多
      *max_width* 个字符的多行文本。 如果签名长度超过 *max_width*，所
      有形参都将位于单独的行。

      如果 *quote_annotation_strings* 为 False，签名中的 *注解* 如果是
      字符串，则显示时不带开合引号。 如果签名是用 "STRING" 格式创建的
      ，或者使用了 "from __future__ import annotations" 格式，那么这很
      有用。

      Added in version 3.13.

      在 3.14 版本发生变更: 增加了 *unquote_annotations* 形参。

   classmethod from_callable(obj, *, follow_wrapped=True, globals=None, locals=None, eval_str=False)

      返回给定的可调用对象 *obj* 的 "Signature" (或其子类)。

      该方法简化了 "Signature" 的子类化操作：

         class MySignature(Signature):
             pass
         sig = MySignature.from_callable(sum)
         assert isinstance(sig, MySignature)

      其行为在其他方面都与 "signature()" 相同。

      Added in version 3.5.

      在 3.10 版本发生变更: 添加了 *globals*, *locals* 和 *eval_str*
      形参。

class inspect.Parameter(name, kind, *, default=Parameter.empty, annotation=Parameter.empty)

   "Parameter" 对象是 *不可变* 对象。 不要直接修改 "Parameter" 对象，
   你可以使用 "Parameter.replace()" 或 "copy.replace()" 来创建一个修改
   后的副本。

   在 3.5 版本发生变更: 现在 Parameter 对象可以被 pickle 并且为
   *hashable*。

   empty

      该类的一个特殊标记来明确指出默认值和标注的缺失。

   name

      参数的名字字符串。这个名字必须是一个合法的 Python 标识符。

      CPython 会为用于实现推导式和生成器表达式的代码对象构造形如 ".0"
      的隐式形参名。

      在 3.6 版本发生变更: 这些形参名会被此模块公开为 "implicit0" 这样
      的名字。

   default

      该参数的默认值。如果该参数没有默认值，这个属性会被设置为
      "Parameter.empty" 。

   annotation

      该参数的标注。如果该参数没有标注，这个属性会被设置为
      "Parameter.empty" 。

   kind

      描述参数值要如何绑定到形参。 可能的取值可通过 "Parameter" 获得 (
      如 "Parameter.KEYWORD_ONLY")，并支持比较与排序，基于以下顺序:

      +--------------------------+------------------------------------------------+
      | 名称                     | 含意                                           |
      |==========================|================================================|
      | *POSITIONAL_ONLY*        | 值必须以位置参数的方式提供。仅限位置参数是在函 |
      |                          | 数定义中出现在 "/" 之前（如果有）的条目。      |
      +--------------------------+------------------------------------------------+
      | *POSITIONAL_OR_KEYWORD*  | 值既可以以关键字参数的形式提供，也可以以位置参 |
      |                          | 数的形式提供（这是 Python 写成的函数的标准绑定 |
      |                          | 行为的）。                                     |
      +--------------------------+------------------------------------------------+
      | *VAR_POSITIONAL*         | 没有绑定到其他形参的位置实参组成的元组。这对应 |
      |                          | 于 Python 函数定义 中的 "*args" 形参。         |
      +--------------------------+------------------------------------------------+
      | *KEYWORD_ONLY*           | 值必须以关键字参数的形式提供。仅限关键字形参是 |
      |                          | 在 Python 函数定义 中出现在 "*" 或 "*args" 之  |
      |                          | 后的条目。                                     |
      +--------------------------+------------------------------------------------+
      | *VAR_KEYWORD*            | 一个未绑定到其他形参的关键字参数的字典。这对应 |
      |                          | 于 Python 函数定义 中的 "**kwargs" 形参。      |
      +--------------------------+------------------------------------------------+

      示例：打印全部没有默认值的仅限关键字参数：

         >>> def foo(a, b, *, c, d=10):
         ...     pass

         >>> sig = signature(foo)
         >>> for param in sig.parameters.values():
         ...     if (param.kind == param.KEYWORD_ONLY and
         ...                        param.default is param.empty):
         ...         print('Parameter:', param)
         Parameter: c

   kind.description

      描述 "Parameter.kind" 的枚举值。

      Added in version 3.8.

      示例：打印全部参数的描述：

         >>> def foo(a, b, *, c, d=10):
         ...     pass

         >>> sig = signature(foo)
         >>> for param in sig.parameters.values():
         ...     print(param.kind.description)
         positional or keyword
         positional or keyword
         keyword-only
         keyword-only

   replace(*[, name][, kind][, default][, annotation])

      根据调用 replace 的实例新建一个 "Parameter" 实例。 要覆盖一个
      "Parameter" 属性，可以传入相应的参数。 要从一个 "Parameter" 中移
      除默认值或/和标注，可以传入 "Parameter.empty"。

         >>> from inspect import Parameter
         >>> param = Parameter('foo', Parameter.KEYWORD_ONLY, default=42)
         >>> str(param)
         'foo=42'

         >>> str(param.replace()) # 将创建一个 'param' 的浅拷贝
         'foo=42'

         >>> str(param.replace(default=Parameter.empty, annotation='spam'))
         "foo: 'spam'"

      "Parameter" 对象也被泛型函数 "copy.replace()" 所支持。

   在 3.4 版本发生变更: 在 Python 3.3 中 "Parameter" 对象在其 "kind"
   被设为 "POSITIONAL_ONLY" 时允许将 "name" 设为 "None"。 现在已不再允
   许这样做。

class inspect.BoundArguments

   调用 "Signature.bind()" 或 "Signature.bind_partial()" 的结果。容纳
   实参到函数的形参的映射。

   arguments

      一个形参名到实参值的可变映射。仅包含显式绑定的参数。对
      "arguments" 的修改会反映到 "args" 和 "kwargs" 上。

      应当在任何参数处理目的中与 "Signature.parameters" 结合使用。

      备注:

         "Signature.bind()" 和 "Signature.bind_partial()" 中采用默认值
        的参数被跳过。然而，如果有需要的话，可以使用
        "BoundArguments.apply_defaults()" 来添加它们。

      在 3.9 版本发生变更:  "arguments" 现在的类型是 "dict"。之前，它
      的类型是 "collections.OrderedDict"。

   args

      位置参数的值的元组。由 "arguments" 属性动态计算。

   kwargs

      由关键字参数值组成的字典。 根据 "arguments" 属性动态计算得到。
      可按位置传入的参数已改为包括在 "args" 中。

   signature

      向所属 "Signature" 对象的一个引用。

   apply_defaults()

      设置缺失的参数的默认值。

      对于变长位置参数 ("*args")，默认值是一个空元组。

      对于变长关键字参数 ("**kwargs") 默认值是一个空字典。

         >>> def foo(a, b='ham', *args): pass
         >>> ba = inspect.signature(foo).bind('spam')
         >>> ba.apply_defaults()
         >>> ba.arguments
         {'a': 'spam', 'b': 'ham', 'args': ()}

      Added in version 3.5.

   "args" 和 "kwargs" 特征属性可被用于调用函数：

      def test(a, *, b):
          ...

      sig = signature(test)
      ba = sig.bind(10, b=20)
      test(*ba.args, **ba.kwargs)

参见:

  **PEP 362** - 函数签名对象。
     包含具体的规范，实现细节和样例。


类与函数
========

inspect.getclasstree(classes, unique=False)

   将给定的类的列表组织成嵌套列表的层级结构。每当一个内层列表出现时，
   它包含的类均派生自紧接着该列表之前的条目的类。每个条目均是一个二元
   组，包含一个类和它的基类组成的元组。如果 *unique* 参数为真值，则给
   定列表中的每个类将恰有一个对应条目。否则，运用了多重继承的类和它们
   的后代将出现多次。

inspect.getfullargspec(func)

   获取一个 Python 函数的形参的名字和默认值。将返回一个 *具名元组*：

   "FullArgSpec(args, varargs, varkw, defaults, kwonlyargs,
   kwonlydefaults, annotations)"

   *args* 是一个位置参数的名字的列表。 *varargs* 是 "*" 形参的名字或
   "None" 表示不接受任意长位置参数时。 *varkw* 是 "**" 参数的名字，或
   "None" 表示不接受任意关键字参数。 *defaults* 是一个包含了默认参数值
   的 *n* 元组分别对应最后 *n* 个位置参数，或 "None" 则表示没有默认值
   。 *kwonlyargs* 是一个仅关键词参数列表，保持定义时的顺序。
   *kwonlydefaults* 是一个字典映射自 *kwonlyargs* 中包含的形参名。
   *annotations* 是一个字典，包含形参值到标注的映射。其中包含一个特殊
   的键 ""return"" 代表函数返回值的标注（如果有的话）。

   注意： "signature()" 和 Signature 对象 提供可调用对象内省更推荐的
   API，并且支持扩展模块 API 中可能出现的额外的行为（比如仅限位置参数
   ）。该函数被保留的主要原因是保持兼容 Python 2 的 "inspect" 模块 API
   。

   在 3.4 版本发生变更: 该函数现在基于 "signature()" 但仍然忽略
   "__wrapped__" 属性，并且在签名中包含绑定方法中的第一个绑定参数。

   在 3.6 版本发生变更: 之前该方法在 Python 3.5 中被文档归为弃用并建议
   改用 "signature()"，但此决定已被撤回以恢复一个明确受支持的标准接口
   用于单一源 Python 2/3 代码自旧式 "getargspec()" API 的迁移。

   在 3.7 版本发生变更: Python 从 3.7 版起才显式地保证了它保持仅关键字
   参数的定义顺序，尽管实践上在 Python 3 中一直保持了这个顺序。

inspect.getargvalues(frame)

   获取传入特定的帧的实参的信息。将返回一个 *具名元组* "ArgInfo(args,
   varargs, keywords, locals)"。 *args* 是一个参数名字的列表。
   *varargs* 和 *keywords* 是 "*" 和 "**" 参数的名字或 "None"。
   *locals* 是给定的帧的局部环境字典。

   备注:

     该函数因疏忽在 Python 3.5 中被错误地标记为弃用。

inspect.formatargvalues(args[, varargs, varkw, locals, formatarg, formatvarargs, formatvarkw, formatvalue])

   将 "getargvalues()" 返回的四个值格式化为美观的参数规格。 format* 的
   参数是对应的可选格式化函数以转化名字和值为字符串。

   备注:

     该函数因疏忽在 Python 3.5 中被错误地标记为弃用。

inspect.getmro(cls)

   返回由类 cls 的全部基类按方法解析顺序组成的元组，包括 cls 本身。所
   有类不会在此元组中出现多于一次。注意方法解析顺序取决于 cls 的类型。
   除非使用一个非常奇怪的用户定义元类型，否则 cls 会是元组的第一个元素
   。

inspect.getcallargs(func, /, *args, **kwds)

   将 *args* 和 *kwds* 绑定到 Python 函数或方法 *func* 的参数名称，就
   像将它们作为调用时传入的参数一样。 对于绑定方法，还会将第一个参数 (
   通常命名为 "self") 绑定到关联的实例。 将返回一个字典，该字典会将参
   数名称（包括 "*" 和 "**" 参数的名称，如果有的话）映射到 *args* 和
   *kwds* 中的值。 对于不正确地调用 *func* 的情况，即 "func(*args,
   **kwds)" 因函数签名不兼容而引发异常的时候，将引发一个相同类型的异常
   并附带相同或相似的消息。 例如：

      >>> from inspect import getcallargs
      >>> def f(a, b=1, *pos, **named):
      ...     pass
      ...
      >>> getcallargs(f, 1, 2, 3) == {'a': 1, 'named': {}, 'b': 2, 'pos': (3,)}
      True
      >>> getcallargs(f, a=2, x=4) == {'a': 2, 'named': {'x': 4}, 'b': 1, 'pos': ()}
      True
      >>> getcallargs(f)
      Traceback (most recent call last):
      ...
      TypeError: f() missing 1 required positional argument: 'a'

   Added in version 3.2.

   自 3.5 版本弃用: 改使用 "Signature.bind()" 和
   "Signature.bind_partial()"。

inspect.getclosurevars(func)

   获取自 Python 函数或方法 *func* 引用的外部名字到它们的值的映射。返
   回一个 *具名元组* "ClosureVars(nonlocals, globals, builtins,
   unbound)"。 *nonlocals* 映射引用的名字到词法闭包变量，*globals* 映
   射到函数的模块级全局， *builtins* 映射到函数体内可见的内置变量。
   *unbound* 是在函数中引用但不能解析到给定的模块全局和内置变量的名字
   的集合。

   如果 *func* 不是 Python 函数或方法，将引发 "TypeError"。

   Added in version 3.3.

inspect.unwrap(func, *, stop=None)

   获取 *func* 所包装的对象。它追踪 "__wrapped__" 属性链并返回最后一个
   对象。

   *stop* 是一个可选的回调，接受包装链的一个对象作为唯一参数，以允许通
   过让回调返回真值使解包装更早中止。如果回调不曾返回一个真值，将如常
   返回链中的最后一个对象。例如， "signature()" 使用该参数来在遇到具有
   "__signature__" 属性的对象时停止解包装。

   如果遇到循环，则引发 "ValueError"。

   Added in version 3.4.

inspect.get_annotations(obj, *, globals=None, locals=None, eval_str=False, format=annotationlib.Format.VALUE)

   计算一个对象的标注字典。

   这是 "annotationlib.get_annotations()" 的别名；有关更多信息，请参阅
   该函数的文档。

   小心:

     此函数可能执行包含在标注中的任意代码。 请参阅 内省注解的安全影响
     了解详情。

   Added in version 3.10.

   在 3.14 版本发生变更: 此函数现在是
   "annotationlib.get_annotations()" 的别名。 将其调用为
   "inspect.get_annotations" 将继续工作。


解释器栈
========

下列函数有些将返回 "FrameInfo" 对象。 出于向下兼容性考虑这些对象允许在
所有属性上执行元组类操作但 "positions" 除外。 此行为已被弃用并可能会在
未来被移除。

class inspect.FrameInfo

   frame

      记录所对应的 帧对象。

   filename

      关联到由此记录所对应的帧对象所执行的代码的文件名称。

   lineno

      关联到由此记录所对应的帧对象所执行的代码的当前行的行号。

   function

      由此记录所对应的帧所执行的函数的名称。

   code_context

      来自由此记录所对应的帧所执行的源代码的上下文行组成的列表。

   index

      在 "code_context" 列表中执行的当前行的索引号。

   positions

      包含关联到由此记录所对应的指令的起始行号，结束行号，起始列偏移量
      和结束列偏移量的 "dis.Positions" 对象。

   在 3.5 版本发生变更: 返回一个 *named tuple* 而非 "tuple"。

   在 3.11 版本发生变更: "FrameInfo" 现在是一个类实例（以便与之前的
   *named tuple* 保持向下兼容）。

class inspect.Traceback

   filename

      关联到由此回溯所对应的帧所执行的代码的文件名称。

   lineno

      关联到由此回溯所对应的帧所执行的代码的当前行的行号。

   function

      由此回溯所对应的帧所执行的函数的名称。

   code_context

      来自由此回溯所对应的帧所执行的源代码的上下文行组成的列表。

   index

      在 "code_context" 列表中执行的当前行的索引号。

   positions

      包含关联到此回溯所对应的帧所执行的指令的起始行号，结束行号，起始
      列偏移量和结束列偏移量的 "dis.Positions" 对象。

   在 3.11 版本发生变更: "Traceback" 现在是一个类实例（以便与之前的
   *named tuple* 保持向下兼容）。

备注:

  保留帧对象的引用（可见于这些函数返回的帧记录的第一个元素）会导致你的
  程序产生循环引用。每当一个循环引用被创建，所有可从产生循环的对象访问
  的对象的生命周期将会被大幅度延长，即便 Python 的可选的循环检测器被启
  用。如果这类循环必须被创建，确保它们会被显式地打破以避免对象销毁被延
  迟从而导致占用内存增加。尽管循环检测器能够处理这种情况，这些帧（包括
  其局部变量）的销毁可以通过在 "finally" 子句中移除循环来产生确定的行
  为。对于循环检测器在编译 Python 时被禁用或者使用 "gc.disable()" 时，
  这样处理更加尤为重要。比如：

     def handle_stackframe_without_leak():
         frame = inspect.currentframe()
         try:
             # 对 frame 执行一些操作
         finally:
             del frame

  如果你希望保持帧更长的时间（比如在之后打印回溯），你也可以通过
  "frame.clear()" 方法打破循环引用。

大部分这些函数支持的可选的 *context* 参数指定返回时包含的上下文的行数
，以当前行为中心。

inspect.getframeinfo(frame, context=1)

   获取关于帧或回溯对象的信息。 将返回一个 "Traceback" 对象。

   在 3.11 版本发生变更: 将返回一个 "Traceback" 对象而非具名元组。

inspect.getouterframes(frame, context=1)

   获取某个帧及其所有外部帧的 "FrameInfo" 对象的列表。 这些帧代表导致
   *frame* 被创建的一系列调用。 返回的列表中的第一个条目代表 *frame*；
   最后一个条目代表在 *frame* 的栈上的最外层调用。

   在 3.5 版本发生变更: 返回一个 *具名元组* "FrameInfo(frame,
   filename, lineno, function, code_context, index)" 的列表。

   在 3.11 版本发生变更: 将返回一个 "FrameInfo" 对象的列表。

inspect.getinnerframes(traceback, context=1)

   获取一个回溯所在的帧及其所有内部帧的 "FrameInfo" 对象的列表。 这些
   帧代表作为 *frame* 的后续所执行的调用。 列表中的第一个条目代表
   *traceback*；最后一个条目代表引发异常的位置。

   在 3.5 版本发生变更: 返回一个 *具名元组* "FrameInfo(frame,
   filename, lineno, function, code_context, index)" 的列表。

   在 3.11 版本发生变更: 将返回一个 "FrameInfo" 对象的列表。

inspect.currentframe()

   返回调用者的栈帧对应的帧对象。

   该函数依赖于 Python 解释器对于栈帧的支持，这并非在 Python 的所有实
   现中被保证。该函数在不支持 Python 栈帧的实现中运行会返回 "None"。

inspect.stack(context=1)

   返回调用者的栈的 "FrameInfo" 对象的列表。 返回的列表中的第一个条目
   代表调用者；最后一个条目代表栈上的最外层调用。

   在 3.5 版本发生变更: 返回一个 *具名元组* "FrameInfo(frame,
   filename, lineno, function, code_context, index)" 的列表。

   在 3.11 版本发生变更: 将返回一个 "FrameInfo" 对象的列表。

inspect.trace(context=1)

   返回介于当前帧和引发了当前正在处理的异常所在的帧之间的栈的
   "FrameInfo" 对象的列表。 列表中的第一个条目代表调用者；最后一个条目
   代表引发异常的位置。

   在 3.5 版本发生变更: 返回一个 *具名元组* "FrameInfo(frame,
   filename, lineno, function, code_context, index)" 的列表。

   在 3.11 版本发生变更: 将返回一个 "FrameInfo" 对象的列表。


静态地获取属性
==============

"getattr()" 和 "hasattr()" 在获取或检查属性是否存在时可以触发代码执行
。 描述器，像特征属性一样，可能会被唤起而 "__getattr__()" 和
"__getattribute__()" 也可能会被调用。

For cases where you want passive introspection, like documentation
tools, this can be inconvenient. "getattr_static()" has a similar
signature as "getattr()" but avoids executing code when it fetches
attributes.

inspect.getattr_static(obj, attr)
inspect.getattr_static(obj, attr, default)

   获取属性而不触发通过描述器协议、"__getattr__()" 或
   "__getattribute__()" 的动态查找。

   注意：该函数可能无法获取 getattr 能获取的全部的属性（比如动态地创建
   的属性），并且可能发现一些 getattr 无法找到的属性（比如描述器会引发
   AttributeError）。它也能够返回描述器对象本身而非实例成员。

   如果实例的 "__dict__" 被其他成员遮盖（比如一个特性）则该函数无法找
   到实例成员。

   Added in version 3.2.

 "getattr_static()" 不解析描述器。比如槽描述器或 C 语言中实现的 getset
描述器。该描述器对象会被直接返回，而不处理底层属性。

你可以用类似下方的代码的方法处理此事。注意，对于任意 getset 描述器，使
用这段代码仍可能触发代码执行。

   # 解析内置描述器类型的示例代码
   class _foo:
       __slots__ = ['foo']

   slot_descriptor = type(_foo.foo)
   getset_descriptor = type(type(open(__file__)).name)
   wrapper_descriptor = type(str.__dict__['__add__'])
   descriptor_types = (slot_descriptor, getset_descriptor, wrapper_descriptor)

   result = getattr_static(some_object, 'foo')
   if type(result) in descriptor_types:
       try:
           result = result.__get__()
       except AttributeError:
           # 描述器可以引发 AttributeError
           # 以提示下层的值不存在
           # 在这种情况下描述器本身必须
           # 执行处理
           pass


生成器、协程和异步生成器的当前状态
==================================

当实现协程调度器或其他更高级的生成器用途时，判断一个生成器是正在执行、
等待启动或继续或执行，又或者已经被终止是非常有用的。
"getgeneratorstate()" 允许方便地判断一个生成器的当前状态。

inspect.getgeneratorstate(generator)

   获取生成器迭代器的当前状态。

   可能的状态是：

   * GEN_CREATED：等待开始执行。

   * GEN_RUNNING：正在被解释器执行。

   * GEN_SUSPENDED：当前挂起于一个 yield 表达式。

   * GEN_CLOSED：执行已经完成。

   Added in version 3.2.

inspect.getcoroutinestate(coroutine)

   获取协程对象的当前状态。该函数设计为用于使用 "async def" 函数创建的
   协程对象，但也能接受任何包括 "cr_running" 和 "cr_frame" 的类似协程
   的对象。

   可能的状态是：

   * CORO_CREATED：等待开始执行。

   * CORO_RUNNING：当前正在被解释器执行。

   * CORO_SUSPENDED：当前挂起于一个 await 表达式。

   * CORO_CLOSED：执行已经完成。

   Added in version 3.5.

inspect.getasyncgenstate(agen)

   获取一个异步生成器对象的当前状态。 该函数设计为用于由 "async def"
   函数创建的使用 "yield" 语句的异步迭代器对象，但也能接受任何具有
   "ag_running" 和 "ag_frame" 属性的类似异步生成器的对象。

   可能的状态是：

   * AGEN_CREATED: 等待开始执行。

   * AGEN_RUNNING: 当前正在被解释器执行。

   * AGEN_SUSPENDED: 当前在 yield 表达式上挂起。

   * AGEN_CLOSED: 执行已经完成。

   Added in version 3.12.

生成器当前的内部状态也可以被查询。这通常在测试目的中最为有用，来保证内
部状态如预期一样被更新：

inspect.getgeneratorlocals(generator)

   获取 *generator* 里的实时局部变量到当前值的映射。返回一个由名字映射
   到值的字典。这与在生成器的主体内调用 "locals()" 是等效的，并且相同
   的警告也适用。

   如果 *generator* 是一个没有关联帧的 *生成器*，则返回一个空字典。如
   果 *generator* 不是一个 Python 生成器对象，则引发 "TypeError"。

   该函数依赖于生成器为内省暴露一个 Python 栈帧，这并非在 Python 的所
   有实现中被保证。在这种情况下，该函数将永远返回一个空字典。

   Added in version 3.3.

inspect.getcoroutinelocals(coroutine)

   该函数可类比于 "getgeneratorlocals()"，只是作用于由 "async def" 函
   数创建的协程。

   Added in version 3.5.

inspect.getasyncgenlocals(agen)

   此函数类似于 "getgeneratorlocals()"，但只适用于由 "async def" 函数
   创建的使用 "yield" 语句的异步生成器对象。

   Added in version 3.12.


代码对象位标志
==============

Python 代码对象有一个 "co_flags" 属性，它是下列旗标的位映射：

inspect.CO_OPTIMIZED

   代码对象已经经过优化，会采用快速局部变量。

inspect.CO_NEWLOCALS

   如果设置，则当代码对象被执行时会新建一个字典作为帧的 "f_locals"。

inspect.CO_VARARGS

   代码对象拥有一个变长位置形参 (类似 "*args")。

inspect.CO_VARKEYWORDS

   代码对象拥有一个可变关键字形参 (类似 "**kwargs")。

inspect.CO_NESTED

   该标志当代码对象是一个嵌套函数时被置位。

inspect.CO_GENERATOR

   当代码对象是一个生成器函数，即调用时会返回一个生成器对象，则该标志
   被置位。

inspect.CO_COROUTINE

   当代码对象是一个协程函数时被置位。当代码对象被执行时它返回一个协程
   。详见 **PEP 492**。

   Added in version 3.5.

inspect.CO_ITERABLE_COROUTINE

   该标志被用于将生成器转变为基于生成器的协程。包含此标志的生成器对象
   可以被用于 "await" 表达式，并可以 "yield from" 协程对象。详见 **PEP
   492**。

   Added in version 3.5.

inspect.CO_ASYNC_GENERATOR

   当代码对象是一个异步生成器函数时该标志被置位。当代码对象被运行时它
   将返回一个异步生成器对象。详见 **PEP 525**。

   Added in version 3.6.

inspect.CO_HAS_DOCSTRING

   当源代码中存在代码对象的文档字符串时设置该标志。 如果设置了，它将是
   "co_consts" 中的第一项。

   Added in version 3.14.

inspect.CO_METHOD

   当代码对象是在类范围内定义的函数时设置该标志。

   Added in version 3.14.

备注:

  The flags are specific to CPython, and may not be defined in other
  Python implementations.  Furthermore, the flags are an
  implementation detail, and can be removed or deprecated in future
  Python releases. It's recommended to use public APIs from the
  "inspect" module for any introspection needs.


缓冲区旗标
==========

class inspect.BufferFlags

   这是一个代表可被传给实现了 缓冲区协议 的对象的 "__buffer__()" 方法
   的旗标的 "enum.IntFlag"。

   这些旗标的含义的说明见 缓冲区请求的类型。

   SIMPLE

   WRITABLE

   FORMAT

   ND

   STRIDES

   C_CONTIGUOUS

   F_CONTIGUOUS

   ANY_CONTIGUOUS

   INDIRECT

   CONTIG

   CONTIG_RO

   STRIDED

   STRIDED_RO

   RECORDS

   RECORDS_RO

   FULL

   FULL_RO

   READ

   WRITE

   Added in version 3.12.


命令行接口
==========

The "inspect" module also provides a basic introspection capability
from the command line.

默认地，命令行接受一个模块的名字并打印模块的源代码。也可通过后缀一个冒
号和目标对象的限定名称来打印一个类或者一个函数。

--details

   打印特定对象的信息而非源码。
