Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python导入究竟是如何工作的?_Python_Import_Module - Fatal编程技术网

Python导入究竟是如何工作的?

Python导入究竟是如何工作的?,python,import,module,Python,Import,Module,我有两种特殊情况,我不明白在Python中导入是如何工作的: 第一种具体情况: 当我在两个不同的Python脚本中导入同一个模块时,该模块不会被导入两次,对吗?Python第一次遇到它时,它被导入,第二次,它是检查模块是否已导入,还是复制 第二种具体情况: 考虑以下名为bla.py的模块: a = 10 from bla import * def Stuff (): return a 然后,我们有foo.py,一个导入bla.py的模块: a = 10 from bla impo

我有两种特殊情况,我不明白在Python中导入是如何工作的:

第一种具体情况:

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

第二种具体情况:

考虑以下名为
bla.py
的模块:

a = 10
from bla import *

def Stuff ():
    return a
然后,我们有
foo.py
,一个导入
bla.py
的模块:

a = 10
from bla import *

def Stuff ():
    return a
然后,我们有一个名为
bar.py
的脚本,由用户执行:

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

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

第1部分

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

选中的第一个位置是
sys.modules
,它是以前导入的所有模块的缓存。[]


第二部分

从foo导入*
a
导入到本地范围。将值赋给
a
时,会用新值替换该值-但不会触及原始
foo.a
变量

因此,除非您
导入foo
并修改
foo.a
,否则两个调用将返回相同的值

对于一个可变类型,如列表或dict,它会有所不同,修改它确实会影响原始变量-但是给它分配一个新值仍然不会修改
foo.whatever

如果您想了解更多详细信息,请查看:

以下构造绑定名称:函数的形式参数、导入语句、类和函数定义(它们绑定定义块中的类或函数名称),以及目标(如果发生在循环头的赋值中,则为标识符),位于except子句头的第二个位置或后面,如with语句中

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

还值得注意的是,
import
语句的确切功能:

  • import foo
    将模块名称绑定到当前作用域中的模块对象,因此如果修改
    foo。无论什么
    ,您都将使用该模块中的名称-任何修改/分配都将影响模块中的变量
  • from foo import bar
    仅将给定名称(即
    foo
    将保持未绑定状态)绑定到
    foo
    中具有相同名称的元素-因此
    bar
    上的操作与前面解释的操作类似
  • from foo import*
    的行为与前一个类似,但它导入所有不带下划线前缀的全局名称。如果模块定义了
    \uuuuuuuuuuuuuuuuuuuu
    ,则只导入此序列中的名称

第三部分(你的问题中根本不存在:p)

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

  • (类、属性、魔术方法等)()
  • (python中变量的工作方式)
  • (如
    import
    yield
    等语句)
  • (块语句,例如
    for
    try
    with

要回答您的第一个问题:

不,python不会被“导入”两次。python加载模块时,会在中检查模块。如果它不在那里,它被放在那里,然后被装载

回答你的第二个问题:

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


关于一个有点相关的主题,从camelot import*
执行
是。

运行代码时发生了什么?您可能会发现以下有趣的内容:和。它们都在Python中处理导入。因为“from foo import*”将模块foo中的所有内容都带到了bar的本地名称空间中,所以我们在bar的本地名称空间中既有函数Stuff,也有变量“a”[就好像它们是在bar模块中创建的一样],那么,为什么将a设置为5并在bar模块中调用stuff不返回5呢?看来ThiefMaster在回答编辑问题上击败了我。我把这个放在这里只是为了保持“
from camelot import*
与常规导入不一样。”因为“from foo import*”将模块foo中的所有内容都带到了bar的本地名称空间中,所以我们在bar的本地名称空间中有函数Stuff和变量“a”[就好像它们是在bar模块中创建的一样],那么为什么将a设置为5并在bar模块中调用stuff不会返回5呢?因为“from foo import*”将模块foo中的所有内容都带到了bar的本地名称空间中,所以我们在bar的本地名称空间中有函数stuff和变量“a”[就好像它们是在bar模块中创建的一样],那么为什么将a设置为5并在bar模块中调用stuff不会返回5呢?