[英]Namespaces with Module Imports
尽管我已经学习Python大约一年了,但是我正在学习Python并仍然是一个初学者。 我正在尝试编写一个在主模块中调用的功能模块。 被调用模块中的每个函数都需要math模块才能运行。 我想知道是否有一种方法可以不将数学模块导入被调用模块中。 这是我所拥有的:
main.py
:
from math import *
import module1
def wow():
print pi
wow()
module1.cool()
module1.py
:
def cool():
print pi
运行main.py
我得到:
3.14159265359
Traceback (most recent call last):
File "Z:\Python\main.py", line 10, in <module>
module1.cool()
File "Z:\Python\module1.py", line 3, in cool
print pi
NameError: global name 'pi' is not defined
我很难理解的是为什么在运行main.py
时出现名称错误。 我知道变量pi
在导入时对主模块变为全局,因为wow
可以访问它。 我也知道cool
在导入时成为主模块的全局对象,因为我可以打印module1.cool
并获取<function cool at 0x02B11AF0>
。 因此,由于cool
在主模块的全局命名空间中,因此程序不应该首先在变量cool
内部查找pi
,然后在其中找不到它时,在main
模块内部查找 pi
并查找在那吗?
解决此问题的唯一方法是将math模块导入module1.py
。 我不喜欢这样的想法,尽管因为它会使事情变得更复杂,并且我喜欢漂亮,简单的代码。 我觉得我即将掌握名称空间,但是在这方面需要帮助。 谢谢。
如回溯所示,问题不在main.py
,而在module1.py
:
Traceback (most recent call last):
File "Z:\Python\main.py", line 10, in <module>
module1.cool()
File "Z:\Python\module1.py", line 3, in cool
print pi
NameError: global name 'pi' is not defined
换句话说, 在module1
,没有全局名称pi
,因为您尚未将其导入。 from math import *
main.py
from math import *
main.py
,这只是将所有内容从math
模块的命名空间导入到main
模块的命名空间中,而不是导入到每个模块的命名空间中。
我认为您在这里缺少的关键是每个模块都有自己的“全局”名称空间。 刚开始时这可能有点令人困惑,因为在诸如C之类的语言中,所有extern
变量和函数共享一个全局名称空间。 但是一旦您克服了这个假设,Python的方式就很有意义了。
所以,如果你想使用pi
从module1
,你所要做的from math import *
在module1.py
。 (或者,您可以找到其他方式注入它—例如, module1.py
可以from main import *
,或者main.py
可以进行module1.pi = pi
,等等。或者您可以将pi
塞入神奇的builtins
/ __builtin__
模块,或使用其他各种技巧。但显而易见的解决方案是在要import
位置进行导入。)
附带说明一下,您通常不希望from foo import *
进行交互交互式解释器或顶级脚本之外的任何操作。 也有例外(例如,一些模块明确设计为以这种方式使用),但经验法则是import foo
或使用from foo import bar, baz
。
“显式胜于隐式”是Python的创建者做出的设计决定(启动python并运行import this
)。
因此,当您运行module1.cool()
,Python不会在main
模块中查找未定义的pi
。
每当需要使用数学模块时,都必须显式导入它-这就是Python的工作方式。
另外,您应避免from X import *
-style导入,这也是一种不好的做法。 在这里,您可以执行以下操作: from math import pi
。
@abarnert的注释中提到的exec
(python 3)或execfile
(python 2)的简单方法可能对某些工作流程很有用。 所需要做的就是将导入行替换为:
exec( open("module1.py").read() ) # python 3
然后您可以简单地使用cool()
而不是module1.cool()
调用函数。 在cool()
,变量pi
行为将像全局变量一样,如OP最初期望的那样。
简而言之,这只是隐藏了一个函数定义,否则该函数定义将出现在主程序的顶部,并且具有优点和缺点。 对于具有多个模块和导入的大型项目,使用exec
(而不是适当的名称空间)可能是一个错误,因为您通常不希望在单个全局名称空间中保留太多内容。
但是对于简单的情况(例如使用Python作为shell脚本), exec
提供了一种简单明了的方法来隐藏共享函数,同时让它们共享全局名称空间。 请注意,在这种情况下,您可能需要进一步考虑函数的命名方式(例如,使用v1_cool
和v2_cool
来跟踪不同的版本,因为您无法执行v1.cool
和v2.cool
)。
在这里使用exec
一个不太明显的缺点是,尽管您可以解决此问题,但是执行的代码中的错误可能不会显示错误的行号: 如何在Python中从exec或execfile获取错误的行号
就像其他人所说的那样,您的module1
实际上没有全局pi
。 一个很好的解决方案是,它仅从math
导入pi
一次,并明确确保您获取的pi
是从module1
获取的pi
:
main.py
:
import module1
def wow():
print module1.pi
wow()
module1.cool()
module1.py
:
from math import pi
def cool():
print pi
在模块内部,您可以简单地from math import pi
定义,这只会from math import pi
,而不是整个math模块。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.