Есть ли общая идиома для предотвращения бессмысленного копирования части для случаев как это:
>>> 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
в моем первом примере не имейте этой функции.
Я понимаю, что для многих приложений, о чем я говорю, была бы микрооптимизация, поэтому прежде чем любой спросит - да, я представил свое приложение, и это - что-то стоящее вызвать беспокойство о для моего случая.
У меня есть одно 'решение' ниже, но любые лучшие идеи приветствуются.
Создание объекта буфера
позволяет избежать копирования среза, но для коротких срезов более эффективно просто сделать копию:
>>> a.extend(buffer(b, 14, 6))
>>> a
bytearray(b'hello world')
Здесь только одна копия сделана из памяти, но затраты на создание буфер
объект более чем уничтожает сохранение. Тем не менее, это должно быть лучше для больших ломтиков. Я не уверен, насколько большим должен быть фрагмент, чтобы этот метод был более эффективным в целом.
Обратите внимание, что для Python 3 (и, возможно, в Python 2.7) вам понадобится объект memoryview
:
>>> a.extend(memoryview(b)[14:20])
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')