一尘不染

Python导入是如何工作的?

python

我有两种不了解如何在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?


阅读 162

收藏
2020-12-20

共1个答案

一尘不染

第1部分

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

首先检查的是sys.modules,以前已导入的所有模块的缓存。[来源]


第2部分

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

因此,除非您import foo进行修改foo.a,否则两个调用将返回相同的值。

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

如果您需要更多详细信息,请访问http://docs.python.org/reference/executionmodel.html

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

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

还值得注意该import语句的确切作用:

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

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

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

2020-12-20