ディクショナリに可変オブジェクトまたはカスタムクラスのオブジェクト(クエリセット、またはDateTimeなど)が含まれている場合、ディクショナリでclear()
を呼び出すと、これらのオブジェクトがメモリから削除されますか? dictをループしてdel
etingすることとは異なる動作をしますか?
例えば。考える
class MyClass(object):
'''Test Class.'''
my_obj_1 = MyClass()
my_obj_2 = MyClass()
my_dict = { 'foo' : my_obj_1, 'bar' : my_obj_2 }
その後です
my_dict.clear()
と同じ
for key in my_dict.keys():
del my_dict[key]
?
dictsに関するPythonドキュメント は、_del d[key]
_が辞書から_d[key]
_を削除し、d.clear()
がすべてのキーを削除するため、基本的にそれらの動作は同じであると述べています。
メモリの問題については、Python「削除」すると、基本的にオブジェクトへの参照を削除します。オブジェクトが変数や他のオブジェクトによって参照されないか、到達不能になると、garbageメモリから削除できますPythonガベージコレクターがあります随時これはこれを行いますどのオブジェクトがガベージであるかをチェックし、それらに割り当てられたメモリを解放します。辞書から削除しているオブジェクトが他の変数によって参照されている場合、それはまだ到達可能であるため、ガベージではないので削除されません。一般的なガベージコレクション、特にpythonのガベージコレクションについて読むことに興味がある場合は、ここにいくつかのリンクがあります。
実際には、両者には非常に小さな違いがあります。 clear()
は、dictで使用されているハッシュセットのメモリを解放しますが、キーを削除しても解放されません。
a = dict.fromkeys(range(1000))
In [10]: sys.getsizeof(a)
Out[10]: 49432
In [11]: a.clear()
In [12]: sys.getsizeof(a)
Out[12]: 280
In [13]: a = dict.fromkeys(range(1000))
In [14]: for i in range(1000):
....: del a[i]
....:
In [15]: sys.getsizeof(a)
Out[15]: 49432
Dictをループして
del
etingすることとは異なる動作をしますか?
ここで、MutableMapping
抽象基本クラスを実装するカスタムクラスがclear()
を「フリー」ミックスインメソッドとして取得することに注意してください。
MutableMapping
サブクラスをインスタンス化するためにオーバーライドする必要があるメソッドは次のとおりです。
___getitem__, __setitem__, __delitem__, __iter__, __len__
_
マッピングクラスに任意の方法でデータを格納できるため、clear()
が実際にデータをクリアする方法を見つける唯一の方法は、これら5つのメソッドの1つ以上を使用することです。さて、clear()
が使用しているメソッドについて推測するかもしれませんが、なぜ実験できるのかを推測しますか?
_import collections
class MyMap(collections.MutableMapping):
def __init__(self, mydict):
self._top_secret_data = mydict
def __getitem__(self, key):
print 'getitem'
return self._top_secret_data[key]
def __setitem__(self, key, value):
raise Exception('where did you want that?')
def __len__(self):
raise Exception('a gentleman never tells')
def __delitem__(self, key):
print '[shredding intensifies]'
del self._top_secret_data[key]
def __iter__(self):
def keygen():
for key in self._top_secret_data:
print 'faster! faster!'
yield key
return iter(keygen())
_
上記で定義したクラスを使用すると、clear()
の実装方法を簡単に確認できます。
_>>> m = MyMap({1:'a', 2:'b', 3:'c'})
>>> m.clear()
faster! faster!
getitem
[shredding intensifies]
faster! faster!
getitem
[shredding intensifies]
faster! faster!
getitem
[shredding intensifies]
>>>
_
つまり、clear()
mixinメソッドは基本的に_for key in self: del self[key]
_として実装されます。
免責事項:dict
などの組み込み型はCに実装されているため、_dict.clear
_メソッドは文字通り_for key in mydict: del mydict[key]
_と同一ではない場合があります。私は舞台裏での最適化、おそらく完全に異なる戦略を期待します-しかし、この例がexpect a clear()
メソッドがPythonで動作する方法についてのアイデアを提供することを願っています。
del d['foo']
を呼び出すのと同じです。エントリを削除するだけですが、キーや値自体には影響しません。
もちろん、それらへの参照が他にない場合は、ガベージコレクタブルになる可能性があります。
delコマンドはリスト内の特定の項目の参照を削除し、clearコマンドはすべてのキーと値のペアを一度にクリアします。そのため、メモリからの参照解除と残りのタスクの両方の機能はガベージコレクターによって行われます。
あなたの場合、2つのMyClass
オブジェクトは共有されます。 my_obj_1
およびmy_obj_2
から引き続きアクセスできます。
あなたもコードを実行しようとしましたか? Python 3.7で例外がスローされます!"RuntimeError:dictionary changed size during iteration":
for key in my_dict.keys():
del my_dict[key]
以前の回答はすべて良いです。私は、delとclearの違いについてさらにいくつかのポイントを追加したかっただけです。
また、2つの変数my_obj_1とmy_obj_2を宣言しました。 my_dictを削除/クリアしても、これらの2つの変数はMyClassオブジェクトへの参照を保持しているため、my_obj_1とmy_obj_2が範囲外になるまで消えません。そのため、MyClassオブジェクトがメモリ(リストなど)を保持している場合、my_dictを削除またはクリアしてメモリを解放することを意図している場合は発生しません!
クラスMyClass(object): '' 'テストクラス。' ''
my_obj_1 = MyClass()my_obj_2 = MyClass()