1

Python にかなり大きなリストmy_listがあり、それを切り捨てたいとします。それを削除するか、新しいリストを に割り当てることで実現できmy_listます。より良いアプローチは何ですか?

my_list = range(1, 10000)

方法 1:

my_list = list() 
print len(my_list) # prints 0

方法 2:

del my_list[:] 
print len(my_list) # prints 0

method2 がこれを行うためのより適切な方法だと思いますが、そうですか?

4

2 に答える 2

6

内部的には、Python は参照カウントと呼ばれるメカニズムを使用して、データがまだアクセス可能かどうかを追跡します。新しい「変数」がデータを参照するたびに、データの参照カウンタ増加します。「変数」がデータを参照しなくなるたびに、データの参照カウンタ減少します。参照カウンターが 0 に達すると、データが削除されます (その「割り当て解除関数」が呼び出されます): http://docs.python.org/2/c-api/refcounting.html

たとえば、これは「大きな」リストを作成します。このリストは、参照カウンターを「増やす」変数がないため、作成されるとすぐに削除されます。

range(1, 10000)

これにより新しいリストが作成され、それを参照してリストmy_listの参照カウンターを「1」に設定できるようになります

my_list = range(1, 10000)

次のステートメントを記述すると、リストの参照カウンターが減少します。他の参照がないと仮定すると、そのカウンターは 0 に達し、リストは削除されます。

my_list = None

最後の例:

my_list = range(1, 10000)
del my_list[:]

これは、10000 項目のリストを作成します。参照カウンタが「1」の場合。2 番目のステートメントは、リストの 10000 項目を削除しますが、空のリストへの参照はまだ 1 つあります。違いがわかりますか?


ところで、参照カウントは自動割り当て解除の優れたメカニズムであり、(Java ガベージ コレクターの反対として) 決定論的であるという利点があります。ただし、参照カウントが機能しないケースが 1 つあります。それは、循環依存関係がある場合です。オブジェクト A は、オブジェクト A を参照するオブジェクト B を参照します。この場合、「円」が壊れていない限り、A または B の参照カウンタはいずれも 0 に到達できません。しかし、これはあなたの質問を超えていると思います。とにかく、マスターされていない循環依存関係を含むプログラムの場合、Python にはそのようなサイクルを解放するためのオプションのガベージ コレクターがあります。デフォルトでは、ガベージ コレクターが有効になっています。確認するのは簡単です:

>>> import gc
>>> gc.isenabled()
True

最後の注意として、そのガベージ コレクターでさえ、ファイナライザー ( ) を使用してオブジェクトを含むサイクルの割り当てを解除しないため、制限があります__del__。その理由については、次のリンクを参照してください http://arctrix.com/nas/python/gc/

于 2013-06-15T08:18:22.557 に答える
1

両方の操作にほぼ同じ時間がかかるため、削除は私が好むものです。またdel、リストに関連付けられているメモリ参照をすべてクリアし、それを新しいリストに割り当てると、古いメモリが適切にクリアされない場合があります。

于 2013-06-15T08:14:40.750 に答える