2012-09-14 22 views
17

多くの場合、あなたは間違いなく、再びリストを使用していないと確信しています、私はメモリがPythonのリストで使用済みメモリをすぐに解放する方法は?

a = [11,22,34,567,9999] 
del a 

に、今リリースでなければなりません願っています私は、あなたが使用することができ、それは本当にメモリを解放するかどうかわからないんだけど

del a[:] 

実際にリストaのすべての要素を削除します。

これを公開するにはどうすればいいですか?

def realse_list(a): 
    del a[:] 
    del a 

あなたの意見を必要とします。

btw、タプルとセットはどうですか?

+9

大量のデータを処理していて実際にMemoryError例外が発生している場合を除き、メモリ管理について心配する必要はありません。 – monkut

答えて

19
def release_list(a): 
    del a[:] 
    del a 

はこれをしない史上ください。 Pythonは自動的に参照されないオブジェクトをすべて解放します。したがって、単純なdel aは、リストが他のどこでも参照されない場合、リストのメモリが解放されることを保証します。そうであれば、個々の項目の一部もまだ参照されていない限り、個々のリスト項目も解放されます(およびそれらからのみ参照されるオブジェクトなど)。

時がdel aよりも多くリリースされる時は、リストが別の場所で参照されるときです。 であるべきではありません。他の誰かがまだそれを使用しています!!!

基本的には、メモリの管理について考えるべきではありません。代わりに、オブジェクトへの参照を管理することを考えてください。すべてのPythonコードの99%で、Pythonは最後に必要としなかったものをすべて整理します。問題はありません。ある関数がその関数内のすべてのローカル変数を終了するたびに、それらがどこかで参照されていないオブジェクトを指している場合、それらは削除され、それらのオブジェクトに含まれるすべてのものにカスケードされます。

大規模なオブジェクト(巨大なリストなど)がある場合、それを使用して何かを実行した後、長期実行(またはメモリ集約型)の部分計算を開始した場合、ここで大きなオブジェクトはサブ計算に必要なではありません。あなたはそれを参照しているので、大きな計算はサブ計算が終了してから復帰するまで解放されません。そのようなケースでは(の場合のみ)、サブ計算を開始する前に大きなオブジェクトへの参照を明示的にdelすることができます。そうすれば、大きなオブジェクトを早期に解放することができますそれを使用している場合、呼び出し元があなたにオブジェクトを渡し、呼び出し元に返された後もそれが必要な場合は、非常にとなります。

+0

** a **がメンバ変数(大きなもの)で、もはやそれを使用しないことがわかっている場合、これは "参照変数"としてカウントされますか? シナリオは単純です:私は大きなリストを処理するオブジェクトを持っています_when_needed_。いくつかのメソッドが呼び出された後、** a **リストが処理され、結果がキャッシュされます。この場合、私はもう**必要がないことを知っています**。 – hsgubert

+1

@hsgubert 'a'があるオブジェクト(メンバ変数)の属性であれば、それはそのオブジェクトの一部で参照されます(オブジェクト自体がどこかで参照されていると仮定します)。しかし、あなたがもうそれを必要としないことが分かっていて、あなたが同じクラスの方法にいるならば、あなたはそれを取り除くためにちょうど "del self.a"することができます。あなたがそのクラスのメソッドにいない場合は、それを混乱させないでください。良いデザインはほとんどの場合、各クラスが独自の属性を管理する責任を負います。プログラムの他の部分がオブジェクトがその属性の1つをもはや必要としないことをランダムに決定できれば、クラスを理解することは非常に難しいです。 – Ben

4

@monkutのメモのように、ほとんどの場合、メモリ管理についてあまり心配する必要はありません。あなたは、あなたが今をやっているし、それはしばらくの間、現在の関数のスコープの外に行くことはありません確信している巨大なリストを持っている場合は、しかし:

del aは、単にそのために自分の名前aを削除しますメモリのチャンク。他の関数や構造体、またはそれを参照しているものがあれば、それは削除されません。このコードがaという名前でそのリストへの唯一の参照を持ち、あなたがCPythonを使用している場合、参照カウンタはそのメモリをただちに解放します。他の実装(PyPy、Jython、IronPython)では、別のガベージコレクタがあるため、すぐにそれを強制終了しないことがあります。

このため、realse_list関数内のdel aステートメントは、呼び出し元に依然として参照があるため、実際には何も行いません。

del a[:]あなたが注意しているように、リストから要素を削除して、おそらくほとんどのメモリ使用量を削除します。

the_set.clear()と同様の動作をすることができます。

これは不変であるため、タプルで行うことができます。del the_tupleであり、誰も他の誰も参照していないことを願っていますが、おそらく巨大なタプルはありません。

+1

この回答は、弱い参照についての議論によって、実質的により完全になります。 – Marcin

1

データ型のメモリ管理とパフォーマンスが心配なのであれば、リンクされた2重キューのようなものを使用しないでください。

最初にそのメモリフットプリントがメモリから飛び散っているので、バットから大きなメモリを連続して割り当てる必要はありません。

2番目のものは、標準のリストとは異なり、中間の要素を指定すると、残りのリストをインデックス内にスライドさせる必要がないため、大きなリストで時間がかかるため、エンキューとデキューのアクセス時間が向上します。

整数だけを使用している場合は、O(log^2n)アクセス時間がリストのほとんどO(N)と比較してバイナリヒープを調べることをお勧めします。

2

PythonはReference Countを使用してそのリソースを管理します。あなたがリストに入れたときに

import sys 
class foo: 
    pass 

b = foo() 
a = [b, 1] 

sys.getrefcount(b) # gives 3 
sys.getrefcount(a) # gives 2 

a = None # delete the list 
sys.getrefcount(b) # gives 2 

は、上記の例では、Bの参照カウントがインクリメントされ、あなたが見ることができるようにあなたがリストを削除するとき、A、Bの参照カウントも減らさます。だからあなたのコードで

def release_list(a): 
    del a[:] 
    del a 

は冗長でした。

要約すると、リストをNoneオブジェクトに割り当てるか、delキーワードを使用して属性辞書からリストを削除するだけです。 (a.k.a、実際のオブジェクトから名前をバインド解除する)。たとえば、

a = None # or 
del a 

オブジェクトの参照カウントがゼロになると、Pythonはメモリを解放します。オブジェクトが確実に削除されるようにするには、オブジェクトを名前、コンテナで参照する他の場所がないことを確認する必要があります。 sys.getrefcountはあなたに2を与える場合

sys.getrefcount(b) # gives 2 

は、それはあなたがオブジェクトの参照を持っていただけであり、あなたが

b = None 

を行うときに、それがメモリから解放されますを意味します。

関連する問題