Python导入如何正常工作?

时间:2012-05-08 15:31:03

标签: python import module

我有两种特殊情况,我不明白导入如何在Python中运行:

第一个具体情况:

当我在两个不同的Python脚本中导入相同的模块时,模块不会导入两次,对吧? Python第一次遇到它时,会导入它,第二次检查模块是否已导入,还是复制了?

第二个具体情况:

考虑以下模块,称为bla.py

a = 10

然后,我们有foo.py,一个导入bla.py的模块:

from bla import *

def Stuff ():
    return a

之后,我们有一个名为bar.py的脚本,由用户执行:

from foo import *
Stuff() #This should return 10 
a = 5
Stuff()

我不知道:Stuff()会返回10还是5?

2 个答案:

答案 0 :(得分:59)

第1部分

模块只加载一次,因此再次导入模块不会造成性能损失。如果您确实希望再次加载/解析它,则必须reload()模块。

  

检查的第一个地方是sys.modules,这是之前导入的所有模块的缓存。 [source]


第2部分

from foo import *a导入到本地范围。将值分配给a时,会将其替换为新值 - 但不会触及原始foo.a变量。

因此,除非您import foo并修改foo.a,否则两次调用都会返回相同的值。

对于诸如列表或字典之类的可变类型,它会有所不同,修改它确实会影响原始变量 - 但为其分配新值仍然不会修改foo.whatever

如果您想了解更详细的信息,请查看http://docs.python.org/reference/executionmodel.html

  

以下构造绑定名称:形式参数到函数,导入语句,类和函数定义(这些绑定定义块中的类或函数名称)和作为标识符的目标如果出现在赋值中,对于循环头,在except子句头的第二个位置或在with语句之后。

两个粗体部分与您相关:首先,名称a在导入期间绑定到foo.a的值。然后,在执行a = 5时,名称a绑定到5。由于修改list / dict不会导致任何绑定,因此这些操作将修改原始操作(bfoo.b绑定到您操作的同一对象)。将新对象分配给b将再次成为绑定操作,从而将bfoo.b分开。

值得注意的是import语句的确切含义:

  • import foo将模块名称绑定到当前作用域中的模块对象,因此如果修改foo.whatever,您将使用该模块中的名称 - 任何修改/赋值都将影响该变量模块。
  • from foo import bar仅将给定名称(即foo将保持未绑定)绑定到foo中具有相同名称的元素 - 因此对bar的操作表现得很好如前所述。
  • from foo import *的行为与前一个相同,但它会导入所有未使用下划线作为前缀的全局名称。如果模块定义__all__,则仅导入此序列中的名称。

第3部分(在您的问题中甚至不存在:p)

python文档非常好并且通常很冗长 - 您可以在那里找到几乎所有与语言相关的问题的答案。以下是一些有用的链接:

答案 1 :(得分:3)

回答你的第一个问题:

不,python没有“导入”两次。当python加载模块时,它会检查sys.modules中的模块。如果它不在那里,它会被放入那里并加载。

回答你的第二个问题:

模块可以定义它们将导出到from camelot import *场景的名称,行为是为现有值创建名称,而不是引用现有变量(python没有引用)。

在某个相关主题上,执行from camelot import *not the same as a regular import