Предотвращение ненужной части, копирующей в Python

Есть ли общая идиома для предотвращения бессмысленного копирования части для случаев как это:

>>> 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 в моем первом примере не имейте этой функции.

Я понимаю, что для многих приложений, о чем я говорю, была бы микрооптимизация, поэтому прежде чем любой спросит - да, я представил свое приложение, и это - что-то стоящее вызвать беспокойство о для моего случая.

У меня есть одно 'решение' ниже, но любые лучшие идеи приветствуются.

6
задан Scott Griffiths 24 February 2010 в 17:44
поделиться

2 ответа

Создание объекта буфера позволяет избежать копирования среза, но для коротких срезов более эффективно просто сделать копию:

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

Здесь только одна копия сделана из памяти, но затраты на создание буфер объект более чем уничтожает сохранение. Тем не менее, это должно быть лучше для больших ломтиков. Я не уверен, насколько большим должен быть фрагмент, чтобы этот метод был более эффективным в целом.

Обратите внимание, что для Python 3 (и, возможно, в Python 2.7) вам понадобится объект memoryview :

>>> a.extend(memoryview(b)[14:20])
5
ответ дан 17 December 2019 в 00:08
поделиться

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')
2
ответ дан 17 December 2019 в 00:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: