Вопрос

Прямо сейчас я буферизую байты, используя строки, StringIO или cStringIO.Но мне часто нужно удалить байты из левой части буфера.Наивный подход перестроил бы весь буфер.Есть ли оптимальный способ сделать это, если усечение влево — очень распространенная операция?Сборщик мусора Python должен фактически собирать усеченные байты.

Любой алгоритм для этого (хранить буфер небольшими частями?) или существующая реализация действительно помогли бы.

Редактировать:

Я пытался использовать для этого представление памяти Python 2.7, но, к сожалению, данные за пределами «представления» не собираются при удалении исходной ссылки:

# (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 '.',
Это было полезно?

Решение

А дек будет эффективен, если операции удаления слева часты (в отличие от использования списка, строки или буфера, для удаления с любого конца амортизируется O(1).Однако это будет более затратно с точки зрения памяти, чем строка, поскольку вы будете хранить каждый символ как отдельный строковый объект, а не как упакованную последовательность.

Альтернативно вы можете создать свою собственную реализацию (например.связанный список строковых/буферных объектов фиксированного размера), который может хранить данные более компактно.

Другие советы

Создайте свой буфер в виде списка символов или строк и разрежьте этот список.Присоединяйтесь только как строка на выходе.Это довольно эффективно для большинства типов поведения «изменяемой строки».

Сборщик мусора соберет усеченные байты, поскольку на них больше нет ссылок в списке.

ОБНОВЛЯТЬ:Для изменения заголовка списка вы можете просто перевернуть список.Это звучит как неэффективная вещь, однако реализация списка в Python оптимизирует это внутренне.

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

Реверсирование - это быстрая, поэтому временное изменение списка часто может ускорить ситуацию, если вам нужно удалить и вставить кучу элементов в начале списка:

L.reverse()
# append/insert/pop/delete at far end
L.reverse()
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top