del
似乎有一些困扰我的记忆。请参阅以下内容:
In [1]: import math
In [2]: math.cos(0)
Out[2]: 1.0
In [3]: del math.cos
In [4]: math.cos(0)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-4-9cdcc157d079> in <module>()
----> 1 math.cos(0)
AttributeError: module 'math' has no attribute 'cos'
精细。让我们看看如果我们删除整个数学包会发生什么:
In [5]: del math
In [6]: math.cos(0)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-6-9cdcc157d079> in <module>()
----> 1 math.cos(0)
NameError: name 'math' is not defined
所以现在数学本身就像预期的那样消失了。
现在让我们再次导入数学:
In [7]: import math
In [8]: math.cos(0)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-8-9cdcc157d079> in <module>()
----> 1 math.cos(0)
AttributeError: module 'math' has no attribute 'cos'
所以交互式python以某种方式记得即使在我们删除了整个数学包并再次导入它之后,math.cos也被删除了。
python在哪里保留这些知识?我们可以访问吗?我们可以改变吗?
答案 0 :(得分:62)
包只从磁盘读取一次,然后作为可变单例存储在内存中。第二次导入它时,您将获得与先前导入的完全相同的单例,并且它仍然缺少其cos
。 del math
只是删除了它的本地名称,它没有&#34; #emp;&#34;整体来自Python的包。
答案 1 :(得分:24)
我会说这个包仍然被视为已导入。因此,再次执行import math
只需重新声明名称,但使用旧内容。
你可以使用reload
来确保你的模块再次完整,除了某些版本的python还要删除sys.modules
中的条目,这样就可以使用reload
冗余:
import math
del math.cos
del math
sys.modules.pop("math") # remove from loaded modules
import math
print(math.cos(0)) # 1.0
(各种python版本reload
和import
之间的差异将在后续问题中讨论:Should importlib.reload restore a deleted attribute in Python 3.6?)
答案 2 :(得分:15)
del math
根本不删除软件包,它只删除当前模块中的本地名称 math
。
与任何其他对象一样,如果对数学模块的任何其他引用存在于任何地方,那么它将保留在内存中。
特别是,sys.modules
始终是所有已加载模块的字典,所以至少在那里总是有一个引用。
编辑:但是有一种方法可以实际重新加载模块imp.reload
。
不幸的是我无法让它在这种情况下工作,重载需要随机模块(可能是创建编译的Python文件的某些部分),随机模块需要math.cos
,它已经消失了。即使首先导入random
也没有错误,但math.cos
不再出现;我不知道为什么,也许是因为它是一个内置模块。