"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 讀取內容。
