symtable — 访问编译器的符号表

源代码: Lib/symtable.py


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

生成符号表

symtable.symtable(code, filename, compile_type)

返回 Python 源码 code 的顶级 SymbolTablefilename 是包含代码的文件名。compile_type 类似于 compile()mode 参数。

检查符号表

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 对象,后两者不支持边界或约束元组)的边界、约束元组或默认值的符号表。

在 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()

返回一个元组,其中包含在类中通过 defasync def 声明的方法式函数的名称。

在这里,“方法”一词指代通过 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 仍然被认为是一个方法式函数。

3.14 版本中已弃用,将在 3.16 版本中移除。

class symtable.Symbol

SymbolTable 中的一个条目,对应于源中的一个标识符。构造函数不公开。

get_name()

返回符号的名称。

is_referenced()

如果符号在其代码块中使用,则返回 True

is_imported()

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

is_parameter()

如果符号是参数,则返回 True

is_type_parameter()

如果符号是类型参数,则返回 True

在 3.14 版本加入。

is_global()

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

is_nonlocal()

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

is_declared_global()

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

is_local()

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

is_annotated()

如果符号已被标注,则返回 True

在 3.6 版本加入。

is_free()

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

is_free_class()

如果类作用域符号从方法的角度来看是自由的,则返回 True

考虑以下示例

def f():
    x = 1  # function-scoped
    class C:
        x = 2  # class-scoped
        def method(self):
            return x

在此示例中,类作用域符号 xC.method 的角度来看被认为是自由的,从而允许后者在运行时返回 1 而不是 2

在 3.14 版本加入。

is_assigned()

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

is_comp_iter()

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

在 3.14 版本加入。

is_comp_cell()

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

在 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

命令行用法

在 3.13 版本加入。

symtable 模块可以作为脚本从命令行执行。

python -m symtable [infile...]

为指定的 Python 源文件生成符号表并转储到标准输出。如果未指定输入文件,则从标准输入读取内容。