Python:惰性子模块导入使父模块无效 > UnboundLocalError - 但为什么呢?
Python: lazy submodule imports invalidate parent modules > UnboundLocalError - But why?
考虑以下代码:
我在我的代码中使用了一个子模块,并且只在一个函数中使用了一个特殊的子模块(加载起来可能非常繁重)所以我懒得导入:
import xml.etree
def y():
print(xml.etree.__name__)
def x():
print(xml.etree.__name__)
import xml.dom
print(xml.dom.__name__)
if __name__ == "__main__":
y()
x()
这将导致 xml
解除绑定:
UnboundLocalError: local variable 'xml' referenced before assignment
(是的,要修复它,我可以在函数中向上移动导入或执行 from xml import dom
)
我很想知道这里发生了什么。
显然,导入是在 Python 进入函数之前计算的。
这背后的原因是什么?
在进入函数之前不评估导入,但在执行之前解析函数体以进行赋值。从主体开始,赋值中绑定的任何名称都被视为函数的局部名称。由于 import
是一种隐式赋值形式,因此名称 xml
只是函数的局部变量。但是您在 import
赋值之前使用它。所以错误其实很明显。
要修复它,您可以照您说的去做,也可以简单地使用 global
:
import xml.etree
def y():
print(xml.etree.__name__)
def x():
global xml
print(xml.etree.__name__)
import xml.dom
print(xml.dom.__name__)
if __name__ == "__main__":
y()
x()
这里有一个更简单的例子:
a = 1
def foo():
print(a) # works
def bar():
print(a) # gives error
a = 2
print(a)
foo()
bar()
这给出:
1
UnboundLocalError: local variable 'a' referenced before assignment
原因是局部变量(和全局变量一样)在编译时确定,覆盖同名的全局变量,但只绑定到值at run-time,因此如果在赋值之前访问它们,则它们是已知的,但尚未定义(例如绑定)。
考虑以下代码: 我在我的代码中使用了一个子模块,并且只在一个函数中使用了一个特殊的子模块(加载起来可能非常繁重)所以我懒得导入:
import xml.etree
def y():
print(xml.etree.__name__)
def x():
print(xml.etree.__name__)
import xml.dom
print(xml.dom.__name__)
if __name__ == "__main__":
y()
x()
这将导致 xml
解除绑定:
UnboundLocalError: local variable 'xml' referenced before assignment
(是的,要修复它,我可以在函数中向上移动导入或执行 from xml import dom
)
我很想知道这里发生了什么。
显然,导入是在 Python 进入函数之前计算的。
这背后的原因是什么?
在进入函数之前不评估导入,但在执行之前解析函数体以进行赋值。从主体开始,赋值中绑定的任何名称都被视为函数的局部名称。由于 import
是一种隐式赋值形式,因此名称 xml
只是函数的局部变量。但是您在 import
赋值之前使用它。所以错误其实很明显。
要修复它,您可以照您说的去做,也可以简单地使用 global
:
import xml.etree
def y():
print(xml.etree.__name__)
def x():
global xml
print(xml.etree.__name__)
import xml.dom
print(xml.dom.__name__)
if __name__ == "__main__":
y()
x()
这里有一个更简单的例子:
a = 1
def foo():
print(a) # works
def bar():
print(a) # gives error
a = 2
print(a)
foo()
bar()
这给出:
1
UnboundLocalError: local variable 'a' referenced before assignment
原因是局部变量(和全局变量一样)在编译时确定,覆盖同名的全局变量,但只绑定到值at run-time,因此如果在赋值之前访问它们,则它们是已知的,但尚未定义(例如绑定)。