# `symtable` ——访问编译器的符号表

Source code： Lib/symtable.py

符号表由编译器在生成字节码之前根据 AST 生成。符号表负责计算代码中每个标识符的作用域。 `symtable` 提供了一个查看这些表的接口。

## 符号表的生成

`symtable.``symtable`(code, filename, compile_type)

  返回 Python 源 代码 顶层的 `SymbolTable`。filename 是代码文件名。 compile_type 的含义类似 `compile()` 的 mode 参数。

## 符号表的查看

class `symtable.``SymbolTable`

  某个代码块的命名空间表。构造函数不公开。

  `get_type`()

    返回符号表的类型。可能是 `'class'` 、`'module'` 或 `'function'`。

  `get_id`()

    返回符号表的标识符

  `get_name`()

    返回符号表的名称。 若为类的符号表则返回类名；若为函数的符号表则为函数名；若是全局符号表则为 `'top'` (`get_type()` 返回 `'module'`)。

  `get_lineno`()

    返回符号表所代表的代码块中第一行的编号。

  `is_optimized`()

    如果符号表中的局部变量可能被优化过，则返回 `True`。

  `is_nested`()

    如果代码块是嵌套类或函数，则返回 `True`。

  `has_children`()

    如果代码块中有嵌套的命名空间，则返回 `True`。可通过 `get_children()` 读取。

  `has_exec`()

    Return `True` if the block uses `exec`.

  `get_identifiers`()

    返回符号表中的符号名列表。

  `lookup`(name)

    在符号表中查找 name 并返回一个 `Symbol` 实例。

  `get_symbols`()

    返回符号表中所有符号的 `Symbol` 实例的列表。

  `get_children`()

    返回嵌套符号表的列表。

class `symtable.``Function`

  函数或方法的命名空间。该类继承自 `SymbolTable`。

  `get_parameters`()

    返回由函数的参数名组成的元组。

  `get_locals`()

    返回函数中局部变量名组成的元组。

  `get_globals`()

    返回函数中全局变量名组成的元组。

  `get_nonlocals`()

    返回函数中非局部变量名组成的元组。

  `get_frees`()

    返回函数中自由变量名组成的元组。

class `symtable.``Class`

  类的命名空间。继承自 `SymbolTable`。

  `get_methods`()

    返回类中声明的方法名组成的元组。

class `symtable.``Symbol`

  `SymbolTable` 中的数据项，对应于源码中的某个标识符。构造函数不公开。

  `get_name`()

    返回符号名

  `is_referenced`()

    如果符号在代码块中被引用了，则返回 `True`。

  `is_imported`()

    如果符号是由导入语句创建的，则返回 `True`。

  `is_parameter`()

    如果符号是参数，返回 `True`。

  `is_global`()

    如果符号是全局变量，则返回 `True`。

  `is_nonlocal`()

    如果符号为非局部变量，则返回 `True`。

  `is_declared_global`()

    如果符号用 global 声明为全局变量，则返回 `True`。

  `is_local`()

    如果符号在代码块内是局部变量，则返回 `True`。

  `is_annotated`()

    如果符号带有注解，则返回 `True`。

    3.6 版新加入.

  `is_free`()

    如果符号在代码块中被引用，但未赋值，则返回 `True`。

  `is_assigned`()

    如果符号在代码块中赋值，则返回 `True`。

  `is_namespace`()

    如果符号名绑定引入了新的命名空间，则返回 `True`。

    如果符号名用于 function 或 class 语句，则为 True。

    例如

        >>> table = symtable.symtable("def some_func(): pass", "string", "exec")
        >>> table.lookup("some_func").is_namespace()
        True

    注意，一个符号名可以与多个对象绑定。如果结果为 `True`，则该符号名还可以绑定到其他对象上，比如 int 或 list ，且不会引入新的命名空间。

  `get_namespaces`()

    返回与符号名绑定的命名空间的列表。

  `get_namespace`()

    返回与符号名绑定的命名空间。如果绑定的命名空间超过一个，则会触发 `ValueError`。