python 符号在同一范围内可以是全局的和局部的

python symbol can be global and local in the same scope

考虑这个函数:

def content(path):
  global file # not useful but valid
  with open(path) as file:
    return file.read()

当生成符号table(使用模块symtable)并在函数content的范围内检查符号file时,它是全局的和局部的同时。调用此函数后,全局名称 file 绑定到文件对象。所以我想知道为什么函数范围内的符号file也被认为是局部符号?

这里是重现该行为的代码(将其放入一个名为 global_and_local.py 的文件中):

import symtable

def content(path):
  global file
  with open(path) as file:
    return file.read()

symtable_root = symtable.symtable(content(__file__), __file__, "exec")
symtable_function = symtable_root.get_children()[0]
symbol_file = symtable_function.lookup('file')
print("symbol 'file' in function scope: is_global() =", symbol_file.is_global())
print("symbol 'file' in function scope: is_local() =", symbol_file.is_local())
print("global scope: file =", file)

生成以下输出:

symbol 'file' in function scope: is_global() = True
symbol 'file' in function scope: is_local() = True
global scope: file = <_io.TextIOWrapper name='global_and_local.py' ...>

出于某种原因,symtable defines is_local 检查符号的任何绑定操作是否出现在范围内(或注释,它们与注释赋值混为一谈在这个阶段):

def is_local(self):
    return bool(self.__flags & DEF_BOUND)

而不是检查符号是否实际上是本地的,这看起来像

def is_local(self):
    return bool(self.__scope in (LOCAL, CELL))

我不确定为什么。这可能是一个错误。我不认为这样的模块有多大用处 - it took over a year before anyone noticed 添加 // 运算符破坏了旧的 parser 模块,所以我很容易看到它被忽视了。