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?
第1部分
该模块只加载一次,所以没有再次导入性能损失。 如果你真的想要它被再次加载/parsing,你必须reload()
模块。
检查的第一个地方是
sys.modules
,以前导入的所有模块的caching。 [ 来源 ]
第2部分
from foo import *
import到本地范围。 当赋值给a
,它被replace为新的值 – 但是原始的foo.a
variables没有被触及。
所以除非你import foo
并修改foo.a
,否则两个调用都会返回相同的值。
对于一个可变types,如列表或字典,它将是不同的,修改它确实会影响原来的variables – 但分配一个新的值将不会修改foo.whatever
。
如果你想了解一些更详细的信息,请看http://docs.python.org/reference/executionmodel.html :
下面的结构绑定名称:函数的forms参数, 导入语句 ,类和函数定义(这些定义块中的类或函数名称绑定在一起),以及作为标识符的目标(如果出现在赋值中)在with语句中的except子句头的位置或之后。
这两个大胆的部分对你来说是相关的:首先,在导入期间,名字a
被绑定到foo.a
的值。 然后,当a = 5
,名字a
被绑定到5
。 由于修改列表/字典不会导致任何绑定,这些操作会修改原来的( b
和foo.b
绑定到您操作相同的对象)。 为b
指定一个新的对象将是一个绑定操作,因此将b
和foo.b
分开。
还值得注意的是, import
声明究竟做了什么:
-
import foo
将模块名称绑定到当前作用域中的模块对象,因此如果修改了foo.whatever
,那么将使用该模块中的名称 – 任何修改/赋值都将影响模块中的variables。 -
from foo import bar
绑定给定名称(即foo
将保持未绑定)到foo
具有相同名称的元素 – 因此,bar
操作行为如前所述。 -
from foo import *
行为与上一行类似,但是它会导入所有未加下划线的全局名称。 如果模块定义了__all__
只有在这个序列中的名字被导入。
第3部分 (甚至不存在你的问题:P)
python文档非常好,通常很冗长 – 你可以在那里find关于几乎所有可能的语言相关问题的答案。 这里有一些有用的链接:
- http://docs.python.org/reference/datamodel.html (类,属性,魔术方法等)()
- http://docs.python.org/reference/executionmodel.html (variables如何在python中工作)
- http://docs.python.org/reference/expressions.html
- http://docs.python.org/reference/simple_stmts.html (如
import
,yield
等语句) - http://docs.python.org/reference/compound_stmts.html (块语句如
for
,try
,with
)
回答你的第一个问题:
不,python不会被“导入”两次。 当python加载模块时,它会检查sys.modules
的模块。 如果它不在那里,就放在那里,然后装上。
要回答你的第二个问题:
模块可以定义他们from camelot import *
场景中导出的名称,行为是为现有值创build名称,而不是引用现有variables(python没有引用)。
在一个有点相关的话题上, from camelot import *
和做一个常规导入不一样 。