# `symtable` --- 存取編譯器的符號表

原始碼：Lib/symtable.py

符號表 (symbol table) 是在生成位元組碼 (bytecode) 之前由編譯器從 AST 生成的。符號表負責計算程式碼中每個識別器 (identifier) 的作用域。`symtable` 提供了一個介面來檢查這些表。

## 產生符號表

symtable.symtable(code, filename, compile_type)

  回傳 Python 原始 code 的頂層 `SymbolTable`。filename 是包含程式碼之檔案之名稱。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"

    用於泛型函式 (generic functions)或泛型類別 (generic classes)的符號表。

  TYPE_VARIABLE = "type variable"

    用於形式意義上 (formal sense) 的繫結、約束元組 (constraint tuple) 或單一型別變數的預設值的符號表，即 TypeVar、TypeVarTuple 或 ParamSpec 物件（後兩者不支援繫結或約束元組）。

  在 3.13 版被加入.

class symtable.SymbolTable

  一個區塊 (block) 的命名空間表 (namespace table) 。建構函式 (constructor) 並不公開。

  get_type()

    回傳符號表的類型。可能的值為 `SymbolTableType` 列舉的成員。

    在 3.12 版的變更: 新增了 `'annotation'`、`'TypeVar bound'`、`'type alias'` 和 `'type parameter'` 作為可能的回傳值。

    在 3.13 版的變更: 回傳值是 `SymbolTableType` 列舉的成員。

    回傳字串的確切值在未來可能會發生變化，因此建議使用 `SymbolTableType` 成員而不是寫死 (hard-coded) 字串。

  get_id()

    回傳表的識別器。

  get_name()

    回傳表的名稱。如果表用於類別，則這是類別的名稱；如果表用於函式，則這是函式的名稱；如果表是全域的，則為 `'top'` （`get_type()` 會回傳 `'module'`）。對於型別參數作用域（用於泛型類別、函式和型別別名），它是底層類別、函式或型別別名的名稱。對於型別別名作用域，它是型別別名的名稱。對於 `TypeVar` 綁定作用域，它會是 `TypeVar` 的名稱。

  get_lineno()

    回傳此表所代表的區塊中第一行的編號。

  is_optimized()

    如果可以最佳化該表中的區域變數，則回傳 `True`。

  is_nested()

    如果區塊是巢狀類別或函式，則回傳 `True`。

  has_children()

    如果區塊內有巢狀命名空間，則回傳 `True`。這些可以透過 `get_children()` 獲得。

  get_identifiers()

    回傳包含表中符號之名稱的視圖物件 (view object)。請參閱視圖物件的文件。

  lookup(name)

    在表中查找 name 並回傳一個 `Symbol` 實例。

  get_symbols()

    回傳表中名稱的 `Symbol` 實例串列。

  get_children()

    回傳巢狀符號表的串列。

class symtable.Function

  一個函式或方法的命名空間。該類別繼承自 `SymbolTable`。

  get_parameters()

    回傳一個包含此函式參數名稱的元組 (tuple)。

  get_locals()

    回傳一個包含此函式中區域變數 (locals) 名稱的元組。

  get_globals()

    回傳一個包含此函式中全域變數 (globals) 名稱的元組。

  get_nonlocals()

    回傳一個包含此函式中明確宣告的非區域變數 (nonlocals) 名稱的元組。

  get_frees()

    回傳一個包含此函式中的自由（閉包）變數 (free (closure) variables) 名稱的元組。

class symtable.Class

  一個類別的命名空間。該類別繼承自 `SymbolTable`。

  get_methods()

    回傳一個包含類別中聲明的類似方法之函式名稱的元組。

    在這裡，術語「方法 (method)」表示透過 `def` 或 `async 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()[1]
        >>> class_A.get_methods()
        ('f', 'g', 'h')

    儘管 `A().f()` 會在 runtime 引發 `TypeError`，但 `A.f` 仍然被視為類似方法的函式。

class symtable.Symbol

  `SymbolTable` 中的條目對應於來源中的識別器。建構函式不是公開的。

  get_name()

    回傳符號的名稱。

  is_referenced()

    如果該符號在其區塊中使用，則回傳 `True`。

  is_imported()

    如果符號是從 import 陳述式建立的，則回傳 `True`。

  is_parameter()

    如果符號是一個參數，則回傳 `True`。

  is_global()

    如果符號是全域的，則回傳 `True`。

  is_nonlocal()

    如果符號是非區域的，則回傳 `True`。

  is_declared_global()

    如果使用全域陳述式將符號聲明為全域的，則回傳 `True`。

  is_local()

    如果符號是其區塊的區域符號，則回傳 `True`。

  is_annotated()

    如果符號有被註釋，則回傳 `True`。

    在 3.6 版被加入.

  is_free()

    如果該符號在其區塊中被參照 (referenced) 但未被賦值 (assigned)，則回傳 `True`。

  is_assigned()

    如果該符號被賦值到其區塊中，則回傳 `True`。

  is_namespace()

    如果名稱綁定引入 (introduce) 新的命名空間，則回傳 `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 原始檔產生符號表並轉儲 (dump) 到 stdout。如果未指定輸入檔案，則從 stdin 讀取內容。