Ответ
collections.deque (двусторонняя очередь) следует использовать вместо списка (list), когда требуется быстрое добавление и удаление элементов с обоих концов коллекции.
Ключевое отличие: Производительность
deque: Операцииappend,pop,appendleft,popleftимеют амортизированную сложность O(1).list:appendиpop(с конца) также имеют сложность O(1), ноinsert(0, ...)иpop(0)(с начала) требуют сдвига всех элементов и имеют сложность O(n).
Основные сценарии использования deque:
- Реализация очередей (FIFO): Использовать
appendдля добавления иpopleftдля извлечения. - Скользящее окно: Хранение N последних элементов из потока данных с помощью параметра
maxlen. - Алгоритмы обхода графов (BFS): Где требуется эффективная очередь для хранения вершин.
Пример:
from collections import deque
# 1. Быстрые операции с обоих концов
d = deque([1, 2, 3])
d.appendleft(0) # O(1) -> deque([0, 1, 2, 3])
d.append(4) # O(1) -> deque([0, 1, 2, 3, 4])
d.popleft() # O(1) -> возвращает 0, d = deque([1, 2, 3, 4])
# 2. Ограничение размера (скользящее окно)
last_five_logs = deque(maxlen=5)
for i in range(10):
last_five_logs.append(f"Log entry {i}")
# deque автоматически удаляет старые элементы
print(last_five_logs)
# Вывод: deque(['Log entry 5', 'Log entry 6', 'Log entry 7', 'Log entry 8', 'Log entry 9'], maxlen=5)
Вывод: Если вам нужна структура данных, оптимизированная для операций в начале и в конце, deque — лучший выбор. Для произвольного доступа по индексу и операций в середине коллекции list остается более эффективным.
Ответ 18+ 🔞
Ага, слушай, вот эта штука collections.deque — это же просто пиздец какой полезный инструмент, если тебе надо быстро пихать и вытаскивать элементы с обоих концов. Представь себе обычный список (list), он же, блядь, как упрямая скотина: добавить что-то в конец — легко, О(1). Но стоит тебе захотеть сунуть что-то в начало — insert(0, ...) — он начинает охуевать и двигать ВСЕ элементы, это уже О(n), ёпта! А если элементов овердохуища? Пиздец, а не производительность.
А вот deque — это как хитрая жопа с двумя карманами. Туда-сюда, в начало, в конец — всё за О(1), потому что внутри это связный список, а не массив. Красота!
Так когда его юзать, спросишь ты?
- Очередь (FIFO), блядь! Самый классический случай.
append— добавил в хвост,popleft()— вытащил из головы. Идеально для задач, где "первым пришел — первым ушел". Никаких тебеpop(0)из списка, которые всё ломают. - Скользящее окно, ёбушки-воробушки! Вот тебе поток данных, а тебе надо хранить только последние N штук. Задаёшь
maxlenпри создании — и всё, он сам, сука, старые записи выкидывает, когда новые приходят. Удобнее некуда. - Обход графа в ширину (BFS). Там же очередь вершин нужна.
deque— то, что доктор прописал.
Смотри, как это выглядит в коде:
from collections import deque
# 1. Быстрые операции с обоих концов — это просто песня!
d = deque([1, 2, 3])
d.appendleft(0) # O(1) — бац, и в начале ноль! deque([0, 1, 2, 3])
d.append(4) # O(1) — и в конец четвёрка! deque([0, 1, 2, 3, 4])
x = d.popleft() # O(1) — выдернул первый элемент (0), d = deque([1, 2, 3, 4])
print(f"Вытащил: {x}, осталось: {d}")
# 2. Скользящее окно — вообще магия, ядрёна вошь!
last_five_logs = deque(maxlen=5) # Всё, больше пяти не влезет
for i in range(10):
last_five_logs.append(f"Запись лога {i}")
# После каждого шага смотри, как оно само чистится
print("Последние 5 записей:", last_five_logs)
# Вывод: deque(['Запись лога 5', 'Запись лога 6', 'Запись лога 7', 'Запись лога 8', 'Запись лога 9'], maxlen=5)
# Видишь? Записи 0-4 сами, нахуй, испарились! Красота.
Итог, чувак: Если тебе надо быстро работать с головами и хвостами — бери deque и не парься. Если же тебе надо постоянно лазить по индексам где-то в середине или менять элементы — тут уже list рулит. Каждый инструмент для своего дела, ёпта. Главное — не пытайся забивать гвозди микроскопом, а то получишь пиздопроебибну.