我知道在 python 中使用 import *
是一种不好的形式,而且我不打算养成它的习惯。然而,我最近遇到了一些我不理解的奇怪行为,想知道是否有人可以向我解释一下。
假设我有三个 python 脚本。第一个 first_script.py
包含:
MESSAGE = 'this is from the first script'
def print_message():
print MESSAGE
if __name__ == '__main__':
print_message()
显然运行这个脚本会给我MESSAGE 的内容。我有第二个脚本,名为 second_script.py
,包括:
import first_script
first_script.MESSAGE = 'this is from the second script'
if __name__ == '__main__':
first_script.print_message()
这种行为(打印这是来自第二个脚本
)对我来说很有意义。我已导入 first_script.py
,但覆盖了其命名空间内的变量,因此当我调用 print_message()
时,我得到了该变量的新内容。
但是,我还有third_script.py
,包括:
from first_script import *
MESSAGE = 'this is from the third script'
if __name__ == '__main__':
print MESSAGE
print_message()
产生的第一行是可以理解的,但第二行对我来说没有意义。我的直觉是,因为我已经通过第一行中的 * 导入到我的主命名空间中,所以我有一个全局变量
称为MESSAGES
。然后在第二行中我覆盖 MESSAGES
。那么为什么该函数(从第一个脚本导入)会产生 OLD 输出,特别是考虑到 Second_script.py 的输出。有什么想法吗?
最佳答案
import module
、from module import smth
和 from module import *
可以有不同的用例。
更简单:
import tools
加载tools
模块并在本地命名空间(也称为tools
)中添加对其的引用。之后,您可以通过在工具引用前面添加 tools
来访问任何工具引用,例如 tools.var1
变体:
import tools as sloot
完全相同,但您使用别名来访问模块中的引用(例如:sloot.var1
)。它主要用于具有众所周知的别名的模块,例如 import numpy as np
。
另一种方式
from tools import foo
直接从当前命名空间的tools
模块导入一些符号。这意味着您只能使用指定的符号,而无需对其进行限定。一个很好的用例是,您可以从具有相同功能的不同模块导入符号。例如
try:
from mod1 import foo
except ImportError:
from mod2 import foo
...
foo() # actually calls foo from mod1 if available else foo from mod2
这通常用作可移植性技巧。
危险:
from tools import *
这是一个常见的习惯用法,但如果模块没有记录它,可能不会达到您的预期。事实上,它从模块导入所有公共(public)符号,默认情况下所有没有开头 _
的符号可能包含不需要的东西。此外,模块可以声明一个特殊变量__all__
,它被假定声明公共(public)接口(interface),在这种情况下,只有__all__
中包含的符号才会被导入。
示例:
mod.py
__all__ = ['foo', 'bar']
def baz(x):
return x * 2
def foo():
return baz('FOO')
def bar():
return baz('BAR')
您可以使用(假设 mod.py 可以访问)
from mod import *
print(foo()) # should print FOOFOO
# ERROR HERE
x = baz("test") # will choke with NameError: baz is not defined
同时
import mod
print(mod.baz("test")) # will display as expected testtest
因此,如果 tools
模块的文档声明它是安全的并列出了实际导入的符号,则应该仅使用 from tools import *
。
关于python - 使用 *(星号)导入与作为 python 中的命名空间导入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26767300/