質問

今、文字列、StringIO、またはcStringIOを使用してバイトをバッファリングしています。しかし、バッファーの左側からバイトを削除する必要がよくあります。単純なアプローチでは、バッファ全体が再構築されます。左切り捨てが非常に一般的な操作である場合、これを行う最適な方法はありますか? Pythonのガベージコレクターは実際に、切り捨てられたバイトをGCする必要があります。

このためのあらゆる種類のアルゴリズム(バッファを小さな断片に維持しますか?)、または既存の実装が本当に役立ちます。

編集:

このためにPython 2.7のメモリビューを使用しようとしましたが、悲しいことに、「ビュー」外のデータは元の参照が削除されたときにGCされません:

# (This will use ~2GB of memory, not 50MB)

memoryview # Requires Python 2.7+

smalls = []

for i in xrange(10):
    big = memoryview('z'*(200*1000*1000))
    small = big[195*1000*1000:]
    del big
    smalls.append(small)
    print '.',
役に立ちましたか?

解決

A deque は、左削除操作が有効な場合に効率的です。頻繁(リスト、文字列、またはバッファを使用する場合とは異なり、両端削除のためにO(1)が償却されます)。ただし、パックされたシーケンスではなく、各文字を独自の文字列オブジェクトとして保存するため、文字列よりもメモリ的にコストがかかります。

別の方法として、独自の実装(たとえば、固定サイズの文字列/バッファオブジェクトのリンクリスト)を作成して、データをよりコンパクトに保存することもできます。

他のヒント

文字または行のリストとしてバッファを構築し、リストをスライスします。出力時に文字列としてのみ結合します。これは、ほとんどのタイプの「可変文字列」動作に対して非常に効率的です。

GCは、リストで参照されなくなったため、切り捨てられたバイトを収集します。

UPDATE:リストヘッドを変更するには、リストを単に逆にすることができます。これは非効率的なことのように思えますが、Pythonのリスト実装はこれを内部的に最適化します。

http://effbot.org/zone/python-list.htm:

  

反転は高速なので、一時的に   多くの場合、リストを逆にすると速度が上がります   あなたが削除する必要がある場合のものと   でアイテムの束を挿入します   リストの先頭:

L.reverse()
# append/insert/pop/delete at far end
L.reverse()
scroll top