Python для начинающих
1.24K subscribers
546 photos
3 videos
232 files
74 links
Python для начинающих
Download Telegram
Понимание и применение генераторов: экономия памяти с yield

Многие новички в Python сначала пишут всё через списки. Это удобно, но не всегда безопасно для памяти. Представьте файл на 10 миллионов строк: загружать его целиком в список — плохая идея. Вот тут и вступают в игру генераторы и ключевое слово yield.

---

### Что такое генератор?

Генератор — это «ленивый» источник данных. Он не хранит все значения сразу, а выдает их по одному по мере запроса. Вместо return в функции используется yield.

def count_up_to(n):
current = 1
while current <= n:
yield current
current += 1

gen = count_up_to(5)
for num in gen:
print(num)


Здесь не создается список [1, 2, 3, 4, 5]. В каждый момент в памяти только одно число.

---

### Генераторы против списков: почему это экономично

# список
squares_list = [i * i for i in range(10_000_000)]

# генератор
squares_gen = (i * i for i in range(10_000_000))


squares_list реально занимает память под 10 млн чисел.
squares_gen — это объект, который умеет по запросу выдавать квадрат очередного числа. Его размер в памяти — примерно как у обычного небольшого объекта, независимо от диапазона.

Используйте генератор, когда:

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

---

### Практический пример: чтение большого файла

def read_large_file(path):
with open(path, 'r', encoding='utf-8') as f:
for line in f:
yield line.strip()

for line in read_large_file('logs.txt'):
if 'ERROR' in line:
print(line)


Мы не загружаем весь файл в память, а читаем его построчно. Для логов, дампов и CSV на гигабайты — это буквально спасение.

---

### Комбинирование генераторов

Генераторы отлично «цепляются» друг за друга:

def even_numbers(numbers):
for n in numbers:
if n % 2 == 0:
yield n

nums = (i for i in range(100)) # генераторное выражение
evens = even_numbers(nums) # генератор-фильтр

for n in evens:
print(n)


Каждый шаг выдает только один элемент: минимум памяти, максимум гибкости.

---

### Главное запомнить

- yield превращает функцию в генератор.
- Генераторы не хранят все данные, а создают их «по требованию».
- Это критично для работы с большими файлами, потоками данных и длинными диапазонами.

Как только ловите себя на том, что создаете огромный список «просто чтобы по нему один раз пройтись» — подумайте: а не пора ли заменить его на генератор?
👍2🔥21
Работа с коллекциями: полезные структуры данных из модуля collections
Работа с коллекциями: полезные структуры данных из collections

Стандартный список и словарь решают 80% задач. Модуль collections помогает закрыть остальные 20% — красиво, быстро и без велосипеда. Разберём самые полезные структуры: Counter, defaultdict, deque и namedtuple.

---

### 1. Counter: кто здесь самый частый?

Counter считает, сколько раз элемент встретился в последовательности.

from collections import Counter

text = "banana apple banana orange apple banana"
words = text.split()

freq = Counter(words)
print(freq) # Counter({'banana': 3, 'apple': 2, 'orange': 1})
print(freq.most_common(1)) # [('banana', 3)]


Удобен для анализа логов, текста, статистики кликов и т.д.

---

### 2. defaultdict: словарь, который не ругается

Обычный словарь выбросит ошибку, если обратиться к несуществующему ключу. defaultdict сам создаст значение по умолчанию.

from collections import defaultdict

scores = [("Alice", 10), ("Bob", 5), ("Alice", 7)]

user_scores = defaultdict(list)
for name, score in scores:
user_scores[name].append(score)

print(user_scores) # {'Alice': [10, 7], 'Bob': [5]}


Отлично подходит для группировки данных.

---

### 3. deque: быстрый список с двух концов

list медленный для вставки/удаления в начале. deque (double-ended queue) делает это за O(1).

from collections import deque

queue = deque()

queue.append("task_1")
queue.append("task_2")
queue.appendleft("urgent_task")

print(queue) # deque(['urgent_task', 'task_1', 'task_2'])

queue.pop() # убрали с конца
queue.popleft() # убрали с начала


Используется для очередей, буферов, слайдинговых окон.

---

### 4. namedtuple: читаемые кортежи

Обычный кортеж — это item[0], item[1] и постоянное забывание, где что. namedtuple даёт имена полям.

from collections import namedtuple

Point = namedtuple("Point", ["x", "y"])
p = Point(3, 4)

print(p.x, p.y) # 3 4
print(p[0], p[1]) # тоже работает


Легковесная альтернатива классам: почти не занимает памяти, но делает код понятнее.

---

Модуль collections — это маленький апгрейд стандартных структур, который сильно упрощает жизнь. Освоив эти четыре инструмента, вы уже будете писать более чистый и эффективный код, чем большинство начинающих.
🔥4
Как работать с типизированными данными с помощью модуля typing
Как подружиться с типами в Python с помощью typing

Python динамический, но иногда это слишком большая свобода. Функция ждёт число, а получает словарь, и ошибка вылезает только в рантайме. Модуль typing помогает заранее описывать, что именно мы ожидаем, и ловить часть ошибок ещё до запуска — с помощью статических анализаторов (например, mypy, PyCharm, VS Code).

---

### Базовые аннотации

from typing import List, Dict

def average(values: List[float]) -> float:
return sum(values) / len(values)

def word_count(texts: List[str]) -> Dict[str, int]:
result: Dict[str, int] = {}
for t in texts:
result[t] = result.get(t, 0) + 1
return result


Здесь мы явно говорим: values — список чисел с плавающей точкой, word_count возвращает словарь слово -> количество.

---

### Optional и Union: когда вариантов несколько

from typing import Optional, Union

def to_int(value: Union[str, float, int]) -> Optional[int]:
try:
return int(value)
except (TypeError, ValueError):
return None


Union означает: параметр может быть одним из перечисленных типов. Optional[int] — просто сокращение для Union[int, None].

---

### Собственные типы с TypedDict

Если вы любите словари, но хотите немного порядка:

from typing import TypedDict

class User(TypedDict):
id: int
name: str
is_active: bool

def greet(user: User) -> str:
status = "active" if user["is_active"] else "inactive"
return f"{user['name']} ({status})"


Теперь статический анализатор предупредит, если вы забудете, например, is_active или передадите строку вместо int для id.

---

### Protocol: утка по правилам

Иногда важен не тип объекта, а то, какие у него есть методы:

from typing import Protocol

class Writer(Protocol):
def write(self, data: str) -> None:
...

def log_message(writer: Writer, message: str) -> None:
writer.write(message + "\n")


Любой объект с методом write(str) -> None подойдёт: файл, буфер, ваш собственный логгер. Это структурная типизация.

---

### Обобщения с TypeVar

Хотите одну функцию для разных типов, но с сохранением информации о них?

from typing import TypeVar, List

T = TypeVar("T")

def first(items: List[T]) -> T:
return items[0]


Если передать List[int], тип результата будет int, а не «что-то неопределённое».

---

Модуль typing не делает код быстрее и не защищает от всех ошибок, но даёт мощный инструмент: формализовать ваши ожидания от данных. А чем точнее формулировки, тем меньше сюрпризов в рантайме.
Создание и экспорт PDF-файлов с помощью библиотеки ReportLab
Создание и экспорт PDF-файлов с помощью ReportLab

PDF любят бухгалтеры, юристы и вообще все, кому важен аккуратный документ “как из принтера”. А Python это тоже умеет — с помощью библиотеки ReportLab.

---

### Установка

pip install reportlab


После этого можно собирать PDF буквально по строчкам.

---

### Самый простой PDF

Создадим файл hello.pdf с одной строкой текста:

from reportlab.pdfgen import canvas

def create_simple_pdf(filename):
c = canvas.Canvas(filename)
c.drawString(100, 750, "Hello, ReportLab!")
c.save()

create_simple_pdf("hello.pdf")


Пара моментов:

- Координаты считаются в поинтах (1/72 дюйма), (0, 0) — левый нижний угол.
- save() обязателен, иначе файл будет пустым.

---

### Добавляем шрифт и несколько строк

Можно управлять шрифтами и цветами:

from reportlab.pdfgen import canvas
from reportlab.lib.colors import blue, red

def create_styled_pdf(filename):
c = canvas.Canvas(filename)

c.setFont("Helvetica-Bold", 20)
c.setFillColor(blue)
c.drawString(100, 780, "Invoice #42")

c.setFont("Helvetica", 12)
c.setFillColor(red)
c.drawString(100, 750, "Customer: John Smith")
c.drawString(100, 730, "Total: $199.99")

c.save()

create_styled_pdf("invoice.pdf")


Так уже можно генерировать простые счета, акты, сертификаты.

---

### Несколько страниц

PDF — не только один лист:

from reportlab.pdfgen import canvas

def create_multipage_pdf(filename):
c = canvas.Canvas(filename)

for page_num in range(1, 4):
c.drawString(100, 750, f"Page {page_num}")
c.showPage() # переход на новую страницу

c.save()

create_multipage_pdf("multipage.pdf")


Каждый вызов showPage() завершает текущую страницу и начинает следующую.

---

### Таблица с использованием platypus

Для отчетов удобен модуль platypus (он входит в ReportLab):

from reportlab.platypus import SimpleDocTemplate, Table, TableStyle
from reportlab.lib import colors

def create_table_pdf(filename):
doc = SimpleDocTemplate(filename)
data = [
["Name", "Quantity", "Price"],
["Apples", 3, "$5"],
["Oranges", 5, "$7"],
["Bananas", 2, "$4"],
]

table = Table(data)
table.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, 0), colors.lightgrey),
("GRID", (0, 0), (-1, -1), 0.5, colors.black),
("ALIGN", (1, 1), (-1, -1), "CENTER"),
]))

doc.build([table])

create_table_pdf("table_report.pdf")


Так уже получается вполне рабочий отчет: заголовки, сетка, выравнивание.

---

ReportLab — мощный “принтер” для Python: формировать счета, договоры, пропуска, сертификаты можно автоматически, просто подставляя данные. Скрипт запускается — и через секунду готов аккуратный PDF, который не стыдно отправить клиенту.
👍1
Основы сериализации объектов с использованием pickle и json
Python для начинающих: основы сериализации с pickle и json

Представьте, что вы написали класс, настроили кучу объектов, а программу нужно закрыть. Как сохранить их состояние, чтобы потом просто "разморозить" и продолжить? Здесь вступает в игру сериализация — превращение объекта в последовательность байт или строку, которую можно записать в файл или отправить по сети.

В Python для этого чаще всего используют два модуля: pickle и json. Они решают похожую задачу, но по-разному.

---

## pickle: все из Python — для Python

pickle умеет сериализовать почти любые Python-объекты: списки, словари, функции, пользовательские классы.

import pickle

class User:
def __init__(self, name, score):
self.name = name
self.score = score

user = User("Alice", 42)

# Сериализация в байты
data = pickle.dumps(user)

# Запись в файл
with open("user.pkl", "wb") as f:
pickle.dump(user, f)

# Чтение из файла
with open("user.pkl", "rb") as f:
loaded_user = pickle.load(f)

print(loaded_user.name, loaded_user.score) # Alice 42


Плюсы:
- поддерживает "почти всё" из мира Python;
- минимум кода.

Минусы:
- формат бинарный и нечитаемый человеком;
- небезопасен: никогда не загружайте pickle-файлы из непроверенных источников — там может быть произвольный вредоносный код.

---

## json: читаемо, переносимо, безопаснее

json сериализует данные в текстовый формат, понятный другим языкам (JavaScript, Go, Java и т.д.). Но он понимает только простые типы: dict, list, str, int, float, bool, None.

import json

user = {
"name": "Alice",
"score": 42,
"tags": ["python", "beginner"]
}

# В строку
json_str = json.dumps(user)

# В файл
with open("user.json", "w", encoding="utf-8") as f:
json.dump(user, f, indent=4)

# Из файла
with open("user.json", "r", encoding="utf-8") as f:
loaded_user = json.load(f)

print(loaded_user["name"], loaded_user["tags"])


Если нужно сериализовать объект своего класса, его придётся "разобрать" в словарь:

class User:
def __init__(self, name, score):
self.name = name
self.score = score

def user_to_dict(user):
return {"name": user.name, "score": user.score}

user = User("Bob", 100)
json_str = json.dumps(user_to_dict(user))


---

## Что когда использовать?

- Нужна максимальная совместимость, читаемый текст и обмен с другими языками — берите json.
- Нужна быстрая работа с "нативными" Python-объектами и файл не покидает ваш сервис — подойдёт pickle, но помните о безопасности.

Сериализация — это способ дать вашим объектам "вторую жизнь" после завершения программы. Освоив pickle и json, вы уже делаете шаг в сторону реальных приложений: конфиги, кэш, сохранения состояния и обмен данными.
👍21
Как использовать модуль time для измерения скорости выполнения
Как использовать модуль time для измерения скорости выполнения кода

Когда код начинает тормозить, первым делом нужно ответить на простой вопрос: что именно работает медленно? Для этого не нужен сложный профайлер — в большинстве случаев хватит стандартного модуля time.

---

### 1. Быстрое измерение через time.time()

Функция time.time() возвращает текущее время в секундах с начала эпохи (обычно 1 января 1970). Если замерить время до и после участка кода — получим длительность его выполнения.

import time

def slow_operation():
total = 0
for i in range(10_000_000):
total += i
return total

start = time.time()
result = slow_operation()
end = time.time()

elapsed = end - start
print(f"Result: {result}")
print(f"Elapsed: {elapsed:.4f} seconds")


Плюс: просто и понятно.
Минус: точность зависит от системы, и эта функция не гарантирует высокую разрешающую способность.

---

### 2. Более точный замер через time.perf_counter()

time.perf_counter() специально создан для измерения интервалов времени. Он не привязан к "реальному" времени, зато максимально точен и не страдает от смены системных часов.

import time

def fast_operation():
return sum(range(10_000_000))

start = time.perf_counter()
result = fast_operation()
end = time.perf_counter()

elapsed = end - start
print(f"Result: {result}")
print(f"Elapsed: {elapsed:.6f} seconds")


Используйте perf_counter() во всех случаях, когда вас интересует скорость кода, а не текущее время.

---

### 3. Сравниваем два варианта решения

Предположим, мы хотим понять, что быстрее: цикл или встроенная функция sum.

import time

def sum_loop(n):
total = 0
for i in range(n):
total += i
return total

def sum_builtin(n):
return sum(range(n))

def measure(func, n, repeats=5):
best = float("inf")
for _ in range(repeats):
start = time.perf_counter()
func(n)
end = time.perf_counter()
elapsed = end - start
if elapsed < best:
best = elapsed
return best

n = 5_000_000
t_loop = measure(sum_loop, n)
t_builtin = measure(sum_builtin, n)

print(f"Loop: {t_loop:.6f} s")
print(f"Builtin: {t_builtin:.6f} s")


Здесь мы запускаем каждую функцию несколько раз и берём лучший результат — так меньше влияние случайных задержек (нагрузка системы, кэш, фоновые процессы).

---

### Вывод

Модуль time — это простой, но мощный инструмент, чтобы:
- измерять скорость отдельных участков кода;
- сравнивать разные реализации;
- находить узкие места без сложных инструментов.

Запомните правило:
time.time() — для "какой сейчас час", time.perf_counter() — для "как быстро это работает".
🔥2
Редактирование изображений с помощью библиотеки pillow (PIL)
### Редактирование изображений с помощью Pillow: первые шаги в «фотошопе на Python»

Pillow — это библиотека, которая превращает Python в мини-фотошоп: можно обрезать, сжимать, накладывать текст, применять фильтры и даже собирать простые превьюшки для соцсетей.

Устанавливается просто:

pip install pillow


Базовый импорт:

from PIL import Image, ImageFilter, ImageEnhance, ImageFont, ImageDraw


---

### Открытие и сохранение изображений

from PIL import Image

img = Image.open("input.jpg") # открываем
print(img.size, img.mode, img.format)

resized = img.resize((800, 600)) # изменение размеров
resized.save("output_resized.jpg", quality=85)


quality=85 полезно для оптимизации картинок под веб.

---

### Обрезка и поворот

img = Image.open("input.jpg")

# crop(left, upper, right, lower)
cropped = img.crop((100, 100, 600, 600))
rotated = cropped.rotate(30, expand=True)

rotated.save("output_cropped_rotated.png")


expand=True не обрежет картинку после поворота.

---

### Фильтры и улучшение качества

from PIL import Image, ImageFilter, ImageEnhance

img = Image.open("input.jpg")

blurred = img.filter(ImageFilter.GaussianBlur(radius=2))
sharpener = ImageEnhance.Sharpness(blurred)
sharpened = sharpener.enhance(1.8) # 1.0 — без изменений

contrast = ImageEnhance.Contrast(sharpened).enhance(1.3)

contrast.save("output_filtered.jpg")


Так можно быстро «подтянуть» резкость и контраст фото.

---

### Нанесение текста (водяной знак)

from PIL import Image, ImageDraw, ImageFont

img = Image.open("input.jpg").convert("RGBA")
txt_layer = Image.new("RGBA", img.size, (0, 0, 0, 0))

draw = ImageDraw.Draw(txt_layer)
font = ImageFont.truetype("arial.ttf", 40)

text = "myblog.dev"
text_pos = (img.size[0] - 250, img.size[1] - 60)

draw.text(text_pos, text, font=font, fill=(255, 255, 255, 120))

watermarked = Image.alpha_composite(img, txt_layer)
watermarked.convert("RGB").save("output_watermarked.jpg")


Здесь создается прозрачный слой, на который рисуется полупрозрачный текст, а затем он накладывается на оригинал.

---

### Массовая обработка изображений

import pathlib
from PIL import Image

input_dir = pathlib.Path("photos")
output_dir = pathlib.Path("photos_optimized")
output_dir.mkdir(exist_ok=True)

for path in input_dir.glob("*.jpg"):
img = Image.open(path)
img.thumbnail((1200, 1200))
img.save(output_dir / path.name, quality=80, optimize=True)


Этот скрипт автоматически уменьшит и сожмет все фото в папке — полезно перед загрузкой на сайт.

---

Pillow хорош тем, что порог входа низкий: уже через пару десятков строк кода можно автоматизировать то, что обычно делается руками в графическом редакторе. А дальше — фильтры, коллажи, генерация превью, мемы и целые пайплайны обработки изображений.
👍2
Мониторинг системных ресурсов с использованием psutil
Мониторинг системных ресурсов с помощью psutil: делаем свой мини‑«Диспетчер задач»

Если вы когда‑нибудь задумывались, как Python‑скрипт может узнать, сколько у вас свободной памяти, насколько загружен процессор и кто вообще ест весь диск — вам нужен модуль psutil.

psutil (process and system utilities) — кроссплатформенная библиотека для работы с системной статистикой: CPU, память, диски, сеть, процессы. Идеален для небольших утилит мониторинга и первых шагов в сторону системного администрирования на Python.

---

### Установка

pip install psutil


---

### Базовый мониторинг CPU и памяти

import psutil
import time

def print_basic_stats():
cpu = psutil.cpu_percent(interval=1)
mem = psutil.virtual_memory()
print(f"CPU: {cpu}%")
print(f"Memory: {mem.percent}% used ({mem.used // (1024**2)} MB / {mem.total // (1024**2)} MB)")

if __name__ == "__main__":
while True:
print_basic_stats()
time.sleep(2)


Здесь:
- cpu_percent(interval=1) замеряет загрузку за последнюю секунду;
- virtual_memory() возвращает объект с подробной статистикой по ОЗУ.

---

### Мониторинг диска и сети

import psutil
import time

def print_disk_and_net():
disk = psutil.disk_usage("/")
net1 = psutil.net_io_counters()
time.sleep(1)
net2 = psutil.net_io_counters()

sent_speed = (net2.bytes_sent - net1.bytes_sent) / 1024
recv_speed = (net2.bytes_recv - net1.bytes_recv) / 1024

print(f"Disk used: {disk.percent}%")
print(f"Net: ↑ {sent_speed:.1f} KB/s, ↓ {recv_speed:.1f} KB/s")

if __name__ == "__main__":
while True:
print_disk_and_net()


Так можно быстро понять, нагружает ли диск какой‑то процесс и есть ли сетевой трафик.

---

### Кто все это ест: процессы

import psutil

def top_memory_processes(limit=5):
processes = []
for proc in psutil.process_iter(["pid", "name", "memory_percent"]):
processes.append(proc.info)
processes.sort(key=lambda p: p["memory_percent"], reverse=True)
for p in processes[:limit]:
print(f"{p['pid']:>6} {p['memory_percent']:5.1f}% {p['name']}")

if __name__ == "__main__":
top_memory_processes()


Функция показывает топ процессов по использованию памяти — уже что‑то вроде урезанного списка в «Диспетчере задач».

---

psutil позволяет вам из простого скрипта превратиться в маленький системный «радист»: собирать метрики, логировать их, строить графики, реагировать на перегрузки. Для начинающего питониста это отличный модуль, чтобы почувствовать, что ваш код взаимодействует не только с текстовыми задачками, но и с «живой» системой.
🔥2
Простое создание ZIP-архивов с zipfile и shutil
### Простое создание ZIP-архивов с zipfile и shutil

Архивация — одна из тех задач, которые рано или поздно понадобятся почти в любом проекте: сделать бэкап, запаковать логи, отправить результаты работы скрипта. В Python это можно сделать «вручную» с модулем zipfile, а можно — «по-быстрому» с shutil. Разберём оба подхода.

---

## Вариант 1: полный контроль с zipfile

zipfile даёт гибкость: можно выбирать режимы сжатия, добавлять отдельные файлы и целые папки, читать содержимое архива.

### Создание архива и добавление файлов

import zipfile
from pathlib import Path

base_dir = Path("project_data")
zip_path = Path("backup.zip")

with zipfile.ZipFile(zip_path, mode="w", compression=zipfile.ZIP_DEFLATED) as zf:
for file_path in base_dir.rglob("*"):
if file_path.is_file():
arc_name = file_path.relative_to(base_dir)
zf.write(file_path, arcname=arc_name)

print(f"Created archive: {zip_path}")


Что тут важно:

- mode="w" — создать новый архив (перезапишет существующий).
- ZIP_DEFLATED — стандартное сжатие.
- relative_to(base_dir) — в архив не попадут «лишние» абсолютные пути.

### Просмотр содержимого архива

import zipfile

with zipfile.ZipFile("backup.zip", "r") as zf:
print(zf.namelist())


Можно и читать файлы напрямую, не распаковывая всё:

with zipfile.ZipFile("backup.zip", "r") as zf:
with zf.open("subdir/report.txt") as f:
content = f.read().decode("utf-8")
print(content)


---

## Вариант 2: быстро и просто с shutil

Если нужен просто «запаковать папку целиком» — shutil.make_archive делает это одной строкой.

import shutil
from pathlib import Path

base_dir = Path("project_data")

archive_path = shutil.make_archive(
base_name="project_backup", # будет project_backup.zip
format="zip",
root_dir=base_dir
)

print(f"Archive created at: {archive_path}")


Можно так же легко создавать не только ZIP, но и tar, gztar, bztar.

---

## Когда что использовать?

- zipfile — когда нужен контроль: выбор файлов, чтение из архива, выбор метода сжатия, обновление существующего архива.
- shutil — когда задача проста: «возьми эту папку и сделай из неё ZIP».

Оба модуля входят в стандартную библиотеку, так что никаких дополнительных установок — просто импортируйте и архивируйте.
👍1
Как класть и извлекать данные из стека и очереди: deque из collections
Как класть и извлекать данные из стека и очереди: deque из collections

Если вам нужны стек или очередь в Python, не спешите писать свои классы. В стандартной библиотеке уже есть мощный инструмент — collections.deque. Это двусторонняя очередь, но из неё легко сделать и стек, и обычную очередь.

---

## Быстрый старт

from collections import deque

dq = deque() # пустая deque
dq = deque([1, 2, 3]) # инициализация с данными


deque оптимизирован под операции добавления/удаления с обоих концов — в отличие от обычного списка, где pop(0) и insert(0, x) работают медленно.

---

## deque как стек (LIFO)

Стек — это принцип “последним пришёл — первым вышел” (LIFO). Для стека нам нужны две операции: положить и достать с одного и того же конца.

from collections import deque

stack = deque()

# кладём в стек
stack.append("page_1")
stack.append("page_2")
stack.append("page_3")

# достаём из стека
last_page = stack.pop() # "page_3"
prev_page = stack.pop() # "page_2"


Здесь append() и pop() работают с “хвостом” очереди. Именно так строится история переходов в браузере, отмена действий в редакторе и т.п.

---

## deque как очередь (FIFO)

Очередь — “первым пришёл — первым вышел” (FIFO). Добавляем в конец, забираем из начала.

from collections import deque

queue = deque()

# приходят задачи
queue.append("task_1")
queue.append("task_2")
queue.append("task_3")

# обрабатываем в порядке поступления
first = queue.popleft() # "task_1"
second = queue.popleft() # "task_2"


Ключевой метод — popleft(): быстро забирает элемент с начала. Для списка аналог pop(0) был бы заметно медленнее.

---

## Двусторонняя очередь

Иногда удобно, что deque — двусторонняя:

from collections import deque

dq = deque([2, 3])

dq.appendleft(1) # слева: [1, 2, 3]
dq.append(4) # справа: [1, 2, 3, 4]

left = dq.popleft() # 1
right = dq.pop() # 4


Так можно, например, реализовать “слайдящуюся” историю последних N элементов.

---

## Ограниченный размер: maxlen

deque умеет автоматически забывать старые элементы:

from collections import deque

history = deque(maxlen=3)

for i in range(5):
history.append(i)

print(history) # deque([2, 3, 4], maxlen=3)


Полезно для логов, последних измерений, кэшей.

---

Главное: запомните четыре метода — append, appendleft, pop, popleft. С их помощью вы можете построить стек, очередь и даже более сложные структуры, не выходя за рамки стандартной библиотеки Python.
👍2
Создание CLI-интерфейсов с библиотекой argparse