我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()
哪个产生:
pprint is in globals() Traceback (most recent call last): File "weird.py", line 9, inif __name__ == '__main__': main() File "weird.py", line 5, in main pprint.pprint('Spam') UnboundLocalError: local variable 'pprint' referenced before assignment
pprint
显然受到以下声明的约束globals
,并将受到约束locals
.有人可以解释为什么它不满意pprint
在globals
这里解决绑定?
编辑:由于回复良好,我可以用相关术语澄清我的问题:
在编译时,标识符pprint
被标记为帧的本地.执行模型是否区分本地标识符绑定在框架内的哪个位置?它可以说,"引用全局绑定直到这个字节码指令,此时它已经反弹到本地绑定",或者执行模型没有考虑到这一点?
哪里出乎意料?您在该范围内重新分配的范围的任何全局变量都由编译器标记为该范围的本地.
如果进口的处理方式不同,那将是令人惊讶的.
但是,可以在不在其中使用符号之后命名模块,反之亦然.
好吧,这对我来说很有趣,我可以通过http://docs.python.org/reference/executionmodel.html阅读.
然后在这里和那里做了一些修补你的代码,这是我能找到的:
码:
import pprint def two(): from pprint import pprint print globals()['pprint'] pprint('Eggs') print globals()['pprint'] def main(): if 'pprint' in globals(): print 'pprint is in globals()' global pprint print globals()['pprint'] pprint.pprint('Spam') from pprint import pprint print globals()['pprint'] pprint('Eggs') def three(): print globals()['pprint'] pprint.pprint('Spam') if __name__ == '__main__': two() print('\n') three() print('\n') main()
输出:
'Eggs' 'Spam' pprint is in globals() 'Spam' 'Eggs'
在该方法中two()
from pprint import pprint
,但不会覆盖名称pprint
中globals
,由于global
关键字未在的范围使用two()
.
在方法中,three()
由于pprint
本地范围中没有名称声明,因此默认为全局名称pprint
,即模块
而在main()
,首先使用关键字global
,因此pprint
方法范围内的所有引用main()
都将引用global
名称pprint
.我们可以看到最初是一个模块,并且global
namespace
正如我们所做的那样用一个方法覆盖from pprint import pprint
虽然这可能没有回答这个问题,但我认为这是一个有趣的事实.
=====================
编辑另一件有趣的事.
如果你有一个模块说:
mod1
from datetime import datetime def foo(): print "bar"
另一种方法说:
mod2
import datetime from mod1 import * if __name__ == '__main__': print datetime.datetime.now()
乍一看,因为你已经导入了模块datetime
,所以看起来是正确的mod2
.
现在,如果您尝试将mod2作为脚本运行,则会抛出错误:
Traceback (most recent call last): File "mod2.py", line 5, inprint datetime.datetime.now() AttributeError: type object 'datetime.datetime' has no attribute 'datetime'
因为第二个导入from mod2 import *
覆盖了datetime
命名空间中的名称,因此第一个导入import datetime
不再有效.
道德:因此,进口的顺序,进口的性质(来自x进口*)和进口模块中的进口意识 - 很重要.