共计 1766 个字符,预计需要花费 5 分钟才能阅读完成。
导读 | 使用 from module import * 默认情况下会导入 module 里的所有变量,若你只想从模块中导入其中几个变量,可以在 module 中使用 __all__ 来控制想要被其他模块导入的变量。 |
使用 from module import * 默认情况下会导入 module 里的所有变量,若你只想从模块中导入其中几个变量,可以在 module 中使用 __all__ 来控制想要被其他模块导入的变量。
# profile.py | |
name='小明' | |
age=18 | |
__all__=['name'] |
打开 python console 验证一下
from profile import * | |
print(name) | |
小明 | |
print(age) | |
Traceback (most recent call last): | |
File "", line 1, in | |
NameError: name 'age' is not defined | |
__all__ 仅对于使用 from module import * 这种情况适用。 |
它经常在一个包的 __init__.py 中出现。
命名空间包,对于不少人来说,可能是一个陌生的名字。
与我们熟悉的常规包不同的是,它没有 __init__.py 文件。
更为特殊的是,它可以跨空间地将两个不相邻的子包,合并成一个虚拟机的包,我们将其称之为 命名空间包。
例如,一个项目的部分代码布局如下
foo-package/ | |
spam/ | |
blah.py | |
bar-package/ | |
spam/ | |
grok.py |
在这 2 个目录里,都有着共同的命名空间 spam。在任何一个目录里都没有__init__.py 文件。
让我们看看,如果将 foo-package 和 bar-package 都加到 python 模块路径并尝试导入会发生什么?
import sys | |
sys.path.extend(['foo-package', 'bar-package']) | |
import spam.blah | |
import spam.grok | |
当一个包为命名空间包时,他就不再和常规包一样具有 __file_ 属性,取而代之的是 __path__
import sys | |
'foo-package', 'bar-package']) | sys.path.extend([|
import spam.blah | |
import spam.grok | |
>>>spam.__path__ | |
_NamespacePath(['foo-package/spam', 'bar-package/spam']) | |
spam.__file__ | |
Traceback (most recent call last): | |
File "", line 1, in | |
AttributeError: 'module' object has no attribute '__file__' |
由于有 sys.modules 的存在,当你导入一个已导入的模块时,实际上是没有效果的。
为了达到模块的重载,有的人会将已导入的包从 sys.modules 中移除后再导入
就像下面这样子
import foo.bar | |
successful to be imported | |
import foo.bar | |
import sys | |
sys.modules['foo.bar'] | |
del sys.modules['foo.bar'] | |
import foo.bar | |
successful to be imported |
上面的例子里我使用的是 import foo.bar,如果你使用的是 from foo import bar 这种导入形式,会发现重载是同样是无效的。
这应该算是一个小坑,不知道的人,会掉入坑中爬不出来。
import foo.bar | |
successful to be imported | |
import foo.bar | |
import sys | |
del sys.modules['foo.bar'] | |
from foo import bar | |
因此,在生产环境中可能需要避免重新加载模块。而在调试模式中,它会提供一定的便利,但你要知道这个重载的弊端,以免掉入坑里。
