web-dev-qa-db-ja.com

パッケージの「del」には何らかのメモリがあります

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'

いいよmathパッケージ全体を削除するとどうなるか見てみましょう。

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は、mathパッケージ全体を削除して再度インポートした後でも削除されたことを覚えています。

pythonはこの知識を保持しますか?アクセスできますか?変更できますか?

43
Aguy

パッケージはまだインポート済みと見なされていると言えます。したがって、import mathを再度実行すると、名前が再宣言されますが、古いコンテンツが含まれます。

いくつかのバージョンのpythonがsys.modulesのエントリも削除する必要があることを除いて、reloadを使用してモジュールが完全であることを確認できます。 of 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バージョン、reloadimportの違いは、次の質問で説明します。 importlib.reloadは、削除された属性をPython 3.6?

23

パッケージはディスクから1回だけ読み取られ、可変シングルトンとしてメモリに保存されます。 2回目にインポートすると、以前にインポートしたものとまったく同じシングルトンが取得されますが、cosがまだありません。 del mathは単にそのローカル名を削除するだけで、Python全体からパッケージを「インポート解除」しません。

62
deceze

del mathはパッケージをまったく削除せず、現在のモジュールのローカル名mathを削除するだけです。

他のオブジェクトと同様に、数学モジュールへの他の参照がどこかに存在する場合、メモリに保持されます。

特に、sys.modulesは常にロードされたすべてのモジュールの辞書なので、少なくともそこには常に参照があります。

編集:しかし、実際にモジュールをリロードする方法があります、imp.reload

残念ながら、この場合は動作しません。リロードにはランダムモジュールが必要です(おそらくコンパイル済みのPythonファイル)の一部を作成するには、ランダムモジュールにはmath.cos、それはなくなった。最初にrandomをインポートしてもエラーはありませんが、math.cosは再表示されません。多分それは組み込みモジュールだからかもしれません。

15
RemcoGerlich