cdl*_*ary 8 python binding scope identifier
我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被标记为帧的本地.执行模型是否区分本地标识符绑定在框架内的哪个位置?它可以说,"引用全局绑定直到这个字节码指令,此时它已经反弹到本地绑定",或者执行模型没有考虑到这一点?
哪里出乎意料?您在该范围内重新分配的范围的任何全局变量都由编译器标记为该范围的本地.
如果进口的处理方式不同,那将是令人惊讶的.
但是,可以在不在其中使用符号之后命名模块,反之亦然.
好吧,这对我来说很有趣,我可以通过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()
Run Code Online (Sandbox Code Playgroud)
输出:
<module 'pprint' from '/usr/lib/python2.5/pprint.pyc'>
'Eggs'
<module 'pprint' from '/usr/lib/python2.5/pprint.pyc'>
<module 'pprint' from '/usr/lib/python2.5/pprint.pyc'>
'Spam'
pprint is in globals()
<module 'pprint' from '/usr/lib/python2.5/pprint.pyc'>
'Spam'
<function pprint at 0xb7d596f4>
'Eggs'
Run Code Online (Sandbox Code Playgroud)
在该方法中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"
Run Code Online (Sandbox Code Playgroud)
另一种方法说:
mod2
import datetime
from mod1 import *
if __name__ == '__main__':
print datetime.datetime.now()
Run Code Online (Sandbox Code Playgroud)
乍一看,因为你已经导入了模块datetime,所以看起来是正确的mod2.
现在,如果您尝试将mod2作为脚本运行,则会抛出错误:
Traceback (most recent call last):
File "mod2.py", line 5, in <module>
print datetime.datetime.now()
AttributeError: type object 'datetime.datetime' has no attribute 'datetime'
Run Code Online (Sandbox Code Playgroud)
因为第二个导入from mod2 import * 覆盖了datetime命名空间中的名称,因此第一个导入import datetime不再有效.
道德:因此,进口的顺序,进口的性质(来自x进口*)和进口模块中的进口意识 - 很重要.
看起来 Python在执行任何代码之前from pprint import pprint都会看到该行并标记pprint为本地名称。由于Python认为pprint应该是一个局部变量,在用语句“赋值”它之前引用它,它会抛出这个错误。 main() pprint.pprint()from..import
这是我所能理解的。
当然,道德是始终将这些import陈述放在范围的顶部。
| 归档时间: |
|
| 查看次数: |
7253 次 |
| 最近记录: |