6

このような場合に無意味なスライスのコピーを避けるための一般的なイディオムはありますか?

>>> a = bytearray(b'hello')
>>> b = bytearray(b'goodbye, cruel world.')
>>> a.extend(b[14:20])
>>> a
bytearray(b'hello world')

b[14:20]スライスの作成時に不要なコピーが発生しているようです。メモリ内に新しいスライスを作成して与えるextendのではなく、「現在のオブジェクトのこの範囲のみを使用する」と言いたいです。

いくつかのメソッドは、スライス パラメーターを使用するのに役立ちます。たとえば、次のようになりますcount

>>> a = bytearray(1000000)       # a million zero bytes
>>> a[0:900000].count(b'\x00')   # expensive temporary slice
900000
>>> a.count(b'\x00', 0, 900000)  # helpful start and end parameters
900000

しかし、最初の例のように、多くのextend場合、この機能はありません。

多くのアプリケーションでは、私が話しているのはマイクロ最適化であることを認識しているので、誰かが尋ねる前に - はい、アプリケーションのプロファイルを作成しました。私の場合は心配する価値があります。

以下に1つの「解決策」がありますが、より良いアイデアは大歓迎です。

4

2 に答える 2

5

オブジェクトを作成するbufferとスライスのコピーを回避できますが、短いスライスの場合はコピーを作成する方が効率的です。

>>> a.extend(buffer(b, 14, 6))
>>> a
bytearray(b'hello world')

ここでは、メモリのコピーが 1 つだけ作成されますが、bufferオブジェクトを作成するコストは、保存を消し去る以上のものです。ただし、より大きなスライスの方が適しているはずです。この方法が全体的により効率的であるためには、スライスがどれくらい大きくなければならないかわかりません。

Python 3 (およびオプションで Python 2.7)では、memoryview代わりにオブジェクトが必要になることに注意してください。

>>> a.extend(memoryview(b)[14:20])
于 2010-02-24T17:44:35.897 に答える
2

itertools持っていisliceます。isliceにはcountメソッドがないため、スライスのコピーを避けたい他の場合に役立ちます。ご指摘のとおり、カウントにはとにかくそのためのメカニズムがあります

>>> from itertools import islice
>>> a = bytearray(1000000)
>>> sum(1 for x in islice(a,0,900000) if x==0)
900000
>>> len(filter(b'\x00'.__eq__,islice(a,0,900000)))
900000

>>> a=bytearray(b"hello")
>>> b = bytearray(b'goodbye, cruel world.')
>>> a.extend(islice(b,14,20))
>>> a
bytearray(b'hello world')
于 2010-02-24T20:49:08.693 に答える