当前位置:  开发笔记 > 编程语言 > 正文

Python全局变量,本地变量和UnboundLocalError

如何解决《Python全局变量,本地变量和UnboundLocalError》经验,为你挑选了2个好方法。

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, in 
    if __name__ == '__main__': main()
  File "weird.py", line 5, in main
    pprint.pprint('Spam')
UnboundLocalError: local variable 'pprint' referenced before assignment

pprint显然受到以下声明的约束globals,并将受到约束locals.有人可以解释为什么它不满意pprintglobals这里解决绑定?

编辑:由于回复良好,我可以用相关术语澄清我的问题:

在编译时,标识符pprint被标记为帧的本地.执行模型是否区分本地标识符绑定在框架内的哪个位置?它可以说,"引用全局绑定直到这个字节码指令,此时它已经反弹到本地绑定",或者执行模型没有考虑到这一点?



1> Albert Visse..:

哪里出乎意料?您在该范围内重新分配的范围的任何全局变量都由编译器标记为该范围的本地.

如果进口的处理方式不同,将是令人惊讶的.

但是,可以在不在其中使用符号之后命名模块,反之亦然.



2> JV...:

好吧,这对我来说很有趣,我可以通过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,但不会覆盖名称pprintglobals,由于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, in 
    print datetime.datetime.now()
AttributeError: type object 'datetime.datetime' has no attribute 'datetime'

因为第二个导入from mod2 import * 覆盖了datetime命名空间中的名称,因此第一个导入import datetime不再有效.

道德:因此,进口的顺序,进口的性质(来自x进口*)和进口模块中的进口意识 - 很重要.

推荐阅读
可爱的天使keven_464
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有