symtable --- 访问编译器的符号表

Source code: Lib/symtable.py


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

符号表的生成

symtable.symtable(code, filename, compile_type, *, module=None)

Return the toplevel SymbolTable for the Python source code. filename is the name of the file containing the code. compile_type is like the mode argument to compile(). The optional argument module specifies the module name. It is needed to unambiguous filter syntax warnings by module name.

Added in version 3.15: Added the module parameter.

符号表的查看

class symtable.SymbolTableType

一个指明 SymbolTable 对象的类型的枚举。

MODULE = "module"

用于模块的符号表。

FUNCTION = "function"

用于函数的符号表。

CLASS = "class"

用于类的符号表。

以下成员指向不同风格的 标注作用域

ANNOTATION = "annotation"

from __future__ import annotations 被激活时用于标注。

TYPE_ALIAS = "type alias"

用于 type 构造的符号表。

TYPE_PARAMETERS = "type parameters"

用于 泛型函数泛型类 的符号表。

TYPE_VARIABLE = "type variable"

用于正式意义下的绑定、约束元组或单个类型变量的默认值的符号变量的符号表,即 TypeVar, TypeVarTuple 或 ParamSpec 对象(后两者不支持绑定或约束元组)。

Added in version 3.13.

class symtable.SymbolTable

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

get_type()

返回符号表的类型。 可能的值为 SymbolTableType 枚举的成员。

在 3.12 版本发生变更: 增加 'annotation', 'TypeVar bound', 'type alias''type parameter' 作为可能的返回值。

在 3.13 版本发生变更: 返回值为 SymbolTableType 枚举的成员。

返回字符串的实际值可能在未来发生变化,因此,建议使用 SymbolTableType 成员而不是硬编码的字符串。

get_id()

返回符号表的标识符

get_name()

返回表名称。 如果表是针对类的则为类名;如果是针对函数的则为函数名;或者如果表是全局的 (get_type() 返回 'module') 则为 'top'。 对于类型形参作用域 (用于泛型类、函数和类型别名),它将为底层类、函数或类型别名的名称。 对于类型别名作用域,它将为类型别名的名称。 对于 TypeVar 绑定作用域,它将为 TypeVar 的名称。

get_lineno()

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

is_optimized()

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

is_nested()

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

has_children()

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

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 语句体中通过 defasync def 定义的函数。

在更深的作用域(例如内部类)中定义的函数不会被 get_methods() 所获取。

例如:

>>> import symtable
>>> st = symtable.symtable('''
... def outer(): pass
...
... class A:
...    def f():
...        def w(): pass
...
...    def g(self): pass
...
...    @classmethod
...    async def h(cls): pass
...
...    global outer
...    def outer(self): pass
... ''', 'test', 'exec')
>>> class_A = st.get_children()[2]
>>> class_A.get_methods()
('f', 'g', 'h')

虽然 A().f() 在运行时会引发 TypeError,但 A.f 仍然被视为是方法型函数。

Deprecated since version 3.14, will be removed in version 3.16.

class symtable.Symbol

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

get_name()

返回符号名

is_referenced()

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

is_imported()

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

is_parameter()

如果符号是参数,返回 True

is_type_parameter()

如果符号是一个类型形参则返回 True

Added in version 3.14.

is_global()

如果符号是全局变量,则返回 True

is_nonlocal()

如果符号为非局部变量,则返回 True

is_declared_global()

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

is_local()

如果符号是代码块内的局部变量,则返回 True

is_annotated()

如果符号带有注解,则返回 True

Added in version 3.6.

is_free()

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

is_free_class()

如果类级作用域的符号对于一个方法来说是自由的则返回 True

比如下面的例子:

def f():
    x = 1  # 函数级作用域
    class C:
        x = 2  # 类级作用域
        def method(self):
            return x

在这个示例中,类级作用域的符号 x 从is considered to be free from the perspective of C.method 的视角来说是自由的,因此允许后者在运行时返回 1 而不是 2

Added in version 3.14.

is_assigned()

如果符号在代码块中赋值,则返回 True

is_comp_iter()

如果符号是一个推导式的迭代变量则返回 True

Added in version 3.14.

is_comp_cell()

如果符号是一个内联推导式中的单元则返回 True

Added in version 3.14.

is_namespace()

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

如果符号名用于函数或类定义语句,则为 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

命令行用法

Added in version 3.13.

symtable 模块可以在命令行下作为脚本来执行。

python -m symtable [infile...]

符号表将针对指定的 Python 文件生成并转储至 stdout。 如果未指定输入文件,将从 stdin 读取内容。