39

ディクショナリに可変オブジェクトまたはカスタムクラスのオブジェクト(クエリセット、さらにはDateTimeなど)が含まれている場合、ディクショナリを呼び出すclear()と、これらのオブジェクトがメモリから削除されますか?deldictをループしてそれらを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]

4

7 に答える 7

64

dictsに関するPythonのドキュメントには、すべてのキーを削除しながら辞書からdel d[key]削除することが記載されているため、基本的にそれらの動作は同じです。d[key]d.clear()

メモリの問題については、Pythonで「削除」すると、基本的にオブジェクトへの参照が削除されます。オブジェクトが変数や他のオブジェクトによって参照されていないか、到達不能になると、そのオブジェクトはガベージになり、メモリから削除できます。Pythonにはガベージコレクターがあり、ガベージコレクターは、どのオブジェクトがガベージであるかをチェックするこのジョブを実行し、それらに割り当てられたメモリを解放しますディクショナリから削除するオブジェクトが他の変数によって参照されている場合でも、到達可能であるため、ガベージではないため、削除されません。ガベージコレクション全般、特にpythonのガベージコレクションについて読みたい場合は、ここにいくつかのリンクを残しておきます。

于 2012-05-04T11:29:22.267 に答える
15

実際、この2つの間にはごくわずかな違いがあります。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
于 2015-05-29T01:55:24.947 に答える
5

deldictをループしてそれらを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()ミックスインメソッドは基本的にとして実装されfor key in self: del self[key]ます。

さて、免責事項:などの組み込み型dictはCで実装されているため、dict.clearメソッドは文字通りと同じではない可能性がありますfor key in mydict: del mydict[key]。舞台裏での最適化、おそらく完全に異なる戦略を期待しますが、この例clear()で、Pythonでメソッドがどのように機能するかについてのアイデアが得られることを願っています。

于 2014-06-06T19:39:02.530 に答える
4

呼び出すのと同じですdel d['foo']。エントリを削除するだけですが、キーや値自体には影響しません。

もちろん、他にそれらへの参照がない場合、それらはゴミ収集可能になる可能性があります。

于 2012-05-04T10:17:03.140 に答える
1

あなたの場合、2つのMyClassオブジェクトは共有されています。my_obj_1とを介して引き続きアクセスできますmy_obj_2

于 2012-05-04T11:04:53.090 に答える
1

delコマンドはリスト内の特定のアイテムの参照を削除し、clearコマンドは外出先ですべてのキーと値のペアをクリアするため、機能は同じであり、間接参照とメモリからの削除の残りのタスクはガベージコレクターによって実行されます

于 2016-01-20T09:24:10.607 に答える
0

コードを実行してみたことはありますか?Python 3.7を使用した次のコードは、例外をスローします。"RuntimeError:反復中に辞書のサイズが変更されました"

for key in my_dict.keys():
    del my_dict[key]

以前の答えはすべて良いです。デルとクリアの違いについて、さらにいくつかのポイントを追加したかっただけです。

  1. my_dict.clear(); 辞書内のすべてのアイテムを削除し、空の辞書と同等にします。注:必要に応じて、アイテムを追加することもできます。
  2. del my_dict; my_dictのオブジェクトが削除され、ガベージコレクションが適格になります(my_dictは使用できなくなります)。したがって、アイテムを追加/アクセスしようとすると、例外が発生します。
  3. また、2つの変数my_obj_1とmy_obj_2を宣言しました。my_dictを削除/クリアしても、これら2つの変数はMyClassオブジェクトへの参照を保持しており、my_obj_1とmy_obj_2がスコープ外になるまで削除されません。したがって、MyClassオブジェクトがメモリ(たとえばリストなど)を保持している場合、my_dictを削除/クリアしてメモリを解放するつもりであれば、それは発生しません。

    class MyClass(object):'''テストクラス。'''

    my_obj_1 = MyClass()my_obj_2 = MyClass()

于 2019-05-05T07:09:44.817 に答える