我UnboundLocalError最近碰到了这个案子,这看起来很奇怪:
import pprint
def main():
if 'pprint' in globals(): print 'pprint is in globals()'
pprint.pprint('Spam')
from pprint import pprint
pprint('Eggs')
if __name__ == '__main__': main()
Run Code Online (Sandbox Code Playgroud)
哪个产生:
pprint is in globals()
Traceback (most recent call last):
File "weird.py", line 9, in <module>
if __name__ == '__main__': main()
File "weird.py", line 5, in main
pprint.pprint('Spam')
UnboundLocalError: local variable 'pprint' referenced before assignment
Run Code Online (Sandbox Code Playgroud)
pprint显然受到以下声明的约束globals,并将受到约束locals.有人可以解释为什么它不满意pprint在globals这里解决绑定?
编辑:由于回复良好,我可以用相关术语澄清我的问题:
在编译时,标识符pprint被标记为帧的本地.执行模型是否区分本地标识符绑定在框架内的哪个位置?它可以说,"引用全局绑定直到这个字节码指令,此时它已经反弹到本地绑定",或者执行模型没有考虑到这一点?
注意:有一个非常类似的问题在这里.但是,请耐心等待; 我的问题不是"为什么会发生错误",而是"为什么Python实现为在这种情况下抛出错误."
我只是偶然发现了这个:
a = 5
def x()
print a
a = 6
x()
Run Code Online (Sandbox Code Playgroud)
抛出一个UnboundLocalException.现在,我确实知道为什么会发生这种情况(后来在这个范围内,a受到限制,因此a在整个范围内都被认为是本地的).
在这种情况下:
a = 5
def x()
print b
b = 6
x()
Run Code Online (Sandbox Code Playgroud)
这非常有意义.但第一种情况有一个直观的逻辑,这意味着:
a = 5
def x()
print globals()["a"]
a = 6 # local assignment
x()
Run Code Online (Sandbox Code Playgroud)
我想有一个原因是为什么不允许"直觉"版本,但它是什么?虽然这可能是"明确比隐含更好"的情况,但摆弄着globals()总觉得我有点不洁净.
从这个角度来看,发生在我身上的实际情况是别人的剧本,我不得不改变一下.在我的(短暂的)更改中,我在脚本运行时进行了一些文件重命名,所以我插入了
import os
os.rename("foo", "bar")
Run Code Online (Sandbox Code Playgroud)
进入脚本.这个插入发生在一个函数内部.模块已经os在顶级导入(我没有检查过),有些os.somefunction调用在函数内部进行,但在插入之前.这些电话显然触发了一个UnboundLocalException.
那么,有人可以向我解释这个实现背后的原因吗?是为了防止用户犯错误?"直观"的方式会让字节码编译器的内容变得更复杂吗?或者是否有一种我没有想到的歧义?