61

如果您的代码的某个子模块加载了一个大模块,那么从该命名空间引用该模块而不是再次导入它有什么好处?

例如:我有一个模块MyLib,它广泛使用了ReallyBigLib。如果我有导入 MyLib 的代码,我应该像这样挖掘模块吗

import MyLib
ReallyBigLib = MyLib.SomeModule.ReallyBigLib

要不就

import MyLib
import ReallyBigLib
4

6 回答 6

83

Python模块可以被视为单例......无论您导入它们多少次,它们都只会被初始化一次,所以最好这样做:

import MyLib
import ReallyBigLib

进口声明的相关文件:

https://docs.python.org/2/reference/simple_stmts.html#the-import-statement

一旦知道模块的名称(除非另有说明,术语“模块”将指包和模块),就可以开始搜索模块或包。检查的第一个地方是 sys.modules,之前已导入的所有模块的缓存。如果在那里找到模块,则在导入的步骤 (2) 中使用它。

导入的模块缓存在sys.modules 中

这是一个将模块名称映射到已经加载的模块的字典。这可以被操纵以强制重新加载模块和其他技巧。请注意,从该字典中删除模块与在相应模块对象上调用 reload() 不同。

于 2008-11-17T16:27:04.760 回答
41

正如其他人指出的那样,Python 维护了一个所有已导入模块的内部列表。当你第一次导入一个模块时,模块(一个脚本)在它自己的命名空间中执行直到结束,内部列表被更新,并在导入语句之后继续执行。

试试这个代码:

   # module/file a.py
   print "Hello from a.py!"
   import b

   # module/file b.py
   print "Hello from b.py!"
   import a

没有循环:只有缓存查找。

>>> import b
Hello from b.py!
Hello from a.py!
>>> import a
>>>

Python 的优点之一是如何将一切都转移到在命名空间中执行脚本。

于 2008-11-18T08:01:14.123 回答
8

它没有实质性的区别。如果已经加载了大模块,则第二个示例中的第二个导入除了将“ReallyBigLib”添加到当前命名空间之外什么都不做。

于 2008-11-17T16:27:44.570 回答
8

警告:Python 不保证模块不会被初始化两次。我遇到过这样的问题。见讨论: http ://code.djangoproject.com/ticket/8193

于 2009-11-04T21:50:58.507 回答
3

导入模块的内部注册表是sys.modules字典,它将模块名称映射到模块对象。您可以在那里查看当前导入的所有模块。

您还可以通过猴子来获取一些有用的技巧(如果需要)sys.modules- 例如将您自己的对象添加为可以由其他模块导入的伪模块。

于 2008-11-19T09:00:41.897 回答
2

在性能方面是相同的。Python 中还没有 JIT 编译器。

于 2008-11-17T16:24:20.023 回答