PyObject *f_builtins; /* builtin symbol table (PyDictObject) */
PyObject *f_globals; /* global symbol table (PyDictObject) */
PyObject *f_locals; /* local symbol table (any mapping) */
这样可以避免在访问全局变量、内建变量时还要通过“访问链”上的回溯来搜索。
PyFrameObject通过如下成员来维护“访问链”(或者称“符号表链”、“名字空间链”):
struct _frame *f_back; /* previous frame, or NULL */
LEGB:符号表的搜索顺序是Local -> Enclosing Function -> Global -> Built-in
一个比较常见而且经典的案例是UnboundLocalError,见如下代码:
x = 10
def foo():
print(x)
x += 1
foo()
这一段代码会出现如下错误:
UnboundLocalError: local variable 'x' referenced before assignment
这个问题可以用下面两段话来解答:
This is because when you make an assignment to a variable in a scope, that variable becomes local to that scope and shadows any similarly named variable in the outer scope. Since the last statement in foo assigns a new value
tox, the compiler recognizes it as a local variable. Consequently when the earlierprintxattempts
to print the uninitialized local variable and an error results.
Otherwise, all variables found outside of the innermost scope areread-only(an attempt to write to such a variable will simply create anewlocal
variable in the innermost scope, leaving the identically named outer variable unchanged).
register PyObject **stack_pointer; /* Next free slot in value stack */
register unsigned char *next_instr;
register int opcode; /* Current opcode */
register int oparg; /* Current opcode argument, if any */
register enum why_code why; /* Reason for block stack unwind */