我有两种特殊情况,我不明白导入如何在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?
答案 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不会导致任何绑定,因此这些操作将修改原始操作(b
和foo.b
绑定到您操作的同一对象)。将新对象分配给b
将再次成为绑定操作,从而将b
与foo.b
分开。
值得注意的是import
语句的确切含义:
import foo
将模块名称绑定到当前作用域中的模块对象,因此如果修改foo.whatever
,您将使用该模块中的名称 - 任何修改/赋值都将影响该变量模块。from foo import bar
仅将给定名称(即foo
将保持未绑定)绑定到foo
中具有相同名称的元素 - 因此对bar
的操作表现得很好如前所述。from foo import *
的行为与前一个相同,但它会导入所有未使用下划线作为前缀的全局名称。如果模块定义__all__
,则仅导入此序列中的名称。第3部分(在您的问题中甚至不存在:p)
python文档非常好并且通常很冗长 - 您可以在那里找到几乎所有与语言相关的问题的答案。以下是一些有用的链接:
import
,yield
)for
,try
,with
等语句答案 1 :(得分:3)
回答你的第一个问题:
不,python没有“导入”两次。当python加载模块时,它会检查sys.modules
中的模块。如果它不在那里,它会被放入那里并加载。
回答你的第二个问题:
模块可以定义它们将导出到from camelot import *
场景的名称,行为是为现有值创建名称,而不是引用现有变量(python没有引用)。
在某个相关主题上,执行from camelot import *
是not the same as a regular import。