包上的 `del` 有某种记忆
`del` on a package has some kind of memory
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 在哪里保存这些知识?我们可以访问它吗?我们可以改变它吗?
包只从磁盘读取一次,然后作为可变单例存储在内存中。第二次导入它时,您会得到与之前导入的完全相同的单例,但它仍然缺少 cos
。 del math
只是删除它的本地名称,它不会 "unimport" 从 Python 整体删除包。
我会说这个包仍然被视为进口的。所以再次执行 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
之间的差异在后续问题中讨论:)
del math
根本不删除包,只是删除当前模块中的local namemath
与任何其他对象一样,如果对数学模块的任何其他引用存在于任何地方,那么它会保存在内存中。
特别是,sys.modules
始终是所有已加载模块的字典,因此至少总有一个引用。
编辑:但是有一种方法可以实际重新加载模块,imp.reload
。
不幸的是,我无法让它在这种情况下工作,重新加载需要随机模块(可能要创建已编译的 Python 文件的某些部分),随机模块需要 math.cos
,它不见了。即使先导入 random
也没有错误,但是 math.cos
不会重新出现;我不知道为什么,可能是因为它是一个内置模块。
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 在哪里保存这些知识?我们可以访问它吗?我们可以改变它吗?
包只从磁盘读取一次,然后作为可变单例存储在内存中。第二次导入它时,您会得到与之前导入的完全相同的单例,但它仍然缺少 cos
。 del math
只是删除它的本地名称,它不会 "unimport" 从 Python 整体删除包。
我会说这个包仍然被视为进口的。所以再次执行 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
之间的差异在后续问题中讨论:
del math
根本不删除包,只是删除当前模块中的local namemath
与任何其他对象一样,如果对数学模块的任何其他引用存在于任何地方,那么它会保存在内存中。
特别是,sys.modules
始终是所有已加载模块的字典,因此至少总有一个引用。
编辑:但是有一种方法可以实际重新加载模块,imp.reload
。
不幸的是,我无法让它在这种情况下工作,重新加载需要随机模块(可能要创建已编译的 Python 文件的某些部分),随机模块需要 math.cos
,它不见了。即使先导入 random
也没有错误,但是 math.cos
不会重新出现;我不知道为什么,可能是因为它是一个内置模块。