混合全局变量/参数与名为'top'的函数时的奇怪Python行为
下面这段代码(不是直接在解释器中运行,而是作为文件执行)
def top(deck):
pass
def b():
global deck
会在
SyntaxError: name 'deck' is local and global
python2.6.4 和
SyntaxError: name 'deck' is parameter and global
python 3.1 上产生错误。
python2.4 似乎可以接受这段代码,2.6.4 的交互式解释器也是如此。
这已经很奇怪了;为什么 'deck' 在一个方法里是全局变量,在另一个方法里却会冲突呢?
但事情变得更奇怪了。把 'top' 改成其他任何名字,问题就消失了。
有人能解释一下这种行为吗?我感觉我这里漏掉了什么很明显的东西。名字 'top' 是不是在某种程度上影响了作用域的内部机制?
更新
这确实看起来是 python 核心的一个 bug。我已经提交了一个 bug 报告。
1 个回答
13
看起来这是在处理符号表时出现了一个错误。Python/symtable.c 里有一些代码(虽然有点复杂),确实把 'top' 当作一个特殊的标识符来处理:
if (!GET_IDENTIFIER(top) ||
!symtable_enter_block(st, top, ModuleBlock, (void *)mod, 0)) {
PySymtable_Free(st);
return NULL;
}
然后稍后又有:
if (name == GET_IDENTIFIER(top))
st->st_global = st->st_cur->ste_symbols;
在文件的更上面,有一个宏:
#define GET_IDENTIFIER(VAR) \
((VAR) ? (VAR) : ((VAR) = PyString_InternFromString(# VAR)))
这个宏使用了 C 语言的预处理器来初始化变量 top
,让它变成一个包含变量名称的字符串。
我觉得符号表可能是用 'top' 这个名字来指代最顶层的代码,但我不知道为什么它不使用一个不会和真实变量冲突的名字。
如果我是你,我会把这个当作一个错误来报告。