我正在学习Python并且仍然是初学者,尽管我已经研究了大约一年了。我正在尝试编写一个在主模块中调用的函数模块。被调用模块中的每个函数都需要运行数学模块。我想知道是否有办法在不调用被调用模块内的数学模块的情况下执行此操作。这就是我所拥有的:
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
和找到它吗?
解决这个问题的唯一方法就是在module1.py
内导入数学模块。我不喜欢这个想法,但是因为它使事情变得更复杂,而且我喜欢漂亮,简单的代码。我觉得我很接近掌握命名空间,但需要帮助。感谢。
答案 0 :(得分:22)
正如追溯所示,问题不在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
时,只需将math
模块命名空间中的所有内容导入main
模块的命名空间,而不是导入每个模块的命名空间。
我认为你在这里缺少的关键是每个模块都有自己的&#34;全球&#34;命名空间。起初这可能有点令人困惑,因为在像C这样的语言中,所有extern
变量和函数共享一个全局命名空间。但是一旦你超越了这个假设,Python的方式就变得非常有意义了。
因此,如果您想使用pi
中的module1
,则必须在from math import *
中执行module1.py
。 (或者您可以找到其他方式来注入它 - 例如,module1.py
可以执行from main import *
,或main.py
可以执行module1.pi = pi
等。或者您可以填写{{ 1}}进入神奇的pi
/ builtins
模块,或者使用其他各种技巧。但显而易见的解决方案是执行您想要导入的__builtin__
。)
作为附注,除了交互式解释器或偶尔的顶级脚本之外,您通常不想在import
任何地方进行操作。有一些例外(例如,明确设计了一些模块用于这种方式),但经验法则是from foo import *
或使用有限的import foo
。
答案 1 :(得分:6)
“明确比隐含更好”是由Python的创建者(启动python并运行import this
)做出的设计决策。
因此,当您运行module1.cool()
时,Python将不会在pi
模块中查找未定义的main
。
当你想要使用它时,你必须明确地导入数学模块 - 这就是Python的工作原理。
另外,你应该避免from X import *
式的导入,这也是不好的做法。在这里,您可以执行:from math import pi
。
答案 2 :(得分:2)
正如其他人所说,pi
实际上并没有全球module1
。一个很好的解决方案就是这个,它只从pi
导入一次math
而显式确保你获得的pi
是来自{{{1}的module1
1}}:
main.py
:
import module1
def wow():
print module1.pi
wow()
module1.cool()
module1.py
:
from math import pi
def cool():
print pi
答案 3 :(得分:2)
@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
的一个不太明显的缺点是,尽管您可以解决以下问题,但是执行的代码中的错误可能不会显示错误的行号:how to get the line number of an error from exec or execfile in Python
答案 4 :(得分:1)
在模块内部,您可以简单地定义from math import pi
,它只会从数学中导入pi而不是整个数学模块。