Python для начинающих
1.24K subscribers
546 photos
3 videos
232 files
74 links
Python для начинающих
Download Telegram
Изучение структур данных: стек и очередь на Python
Изучение структур данных: стек и очередь на Python

Если вы пишете код «как-нибудь в списки», рано или поздно всё превращается в хаос. Структуры данных — это способ договориться с самим собой, как именно вы пользуетесь коллекцией. Сегодня разберём две классики: стек и очередь.

---

### Стек: принцип «последним пришёл — первым ушёл» (LIFO)

Стек — как стопка тарелок: снимаем сверху, кладём тоже сверху.

В Python стек удобно реализовать обычным списком:

stack = []

# push
stack.append(1)
stack.append(2)
stack.append(3)

print(stack) # [1, 2, 3]

# pop (снимаем с вершины)
top = stack.pop()
print(top) # 3
print(stack) # [1, 2]

# просмотр вершины без удаления
peek = stack[-1]
print(peek) # 2


Где это полезно:
- отмена действий (undo),
- обход деревьев,
- проверка правильности скобок в строке.

Мини‑пример проверки скобок:

def is_brackets_balanced(expr: str) -> bool:
stack = []
pairs = {')': '(', ']': '[', '}': '{'}
for ch in expr:
if ch in '([{':
stack.append(ch)
elif ch in ')]}':
if not stack or stack.pop() != pairs[ch]:
return False
return not stack

print(is_brackets_balanced("(a[b]{c})")) # True
print(is_brackets_balanced("(a[b]{c}")) # False


---

### Очередь: «первым пришёл — первым ушёл» (FIFO)

Очередь — как линия в супермаркете: обслуживают по порядку.

Наивный вариант через список:

queue = []
queue.append("task1")
queue.append("task2")
queue.append("task3")

first = queue.pop(0) # медленно на больших данных
print(first) # task1


Проблема: pop(0) сдвигает весь список, что дорого по времени. Для нормальной очереди используем collections.deque:

from collections import deque

queue = deque()

queue.append("task1")
queue.append("task2")
queue.append("task3")

first = queue.popleft()
print(first) # task1
print(queue) # deque(['task2', 'task3'])


deque оптимизирован под быстрые операции с обоих концов.

---

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

- Стек — когда важно вернуться назад: история браузера, рекурсивные алгоритмы, разбор выражений.
- Очередь — когда задачи должны обрабатываться по мере поступления: обработка запросов, планирование задач, очереди сообщений.

Понимание этих двух структур — фундамент для более сложных: деревьев, графов, очередей с приоритетами. И да, в Python почти всегда достаточно list и deque, вопрос только в том, как вы их используете.
2👍1🔥1
Сериализация с помощью модуля pickle: плюсы и минусы
Сериализация с помощью pickle: плюсы и минусы

В какой‑то момент каждый питонист приходит к вопросу: как сохранить объект «как есть», а потом просто загрузить и продолжить работу? Стандартный ответ в мире Python — модуль pickle. Он умеет превращать почти любые объекты в байты и обратно. Но у этой магии есть цена.

---

### Что такое pickle?

pickle — это бинарный формат сериализации Python‑объектов.
То есть:

- сериализация — превращаем объект в байтовую строку;
- десериализация — восстанавливаем объект из байтов.

Простейший пример:

import pickle

data = {"user": "alice", "score": 42, "tags": ["python", "pickle"]}

with open("data.pkl", "wb") as f:
pickle.dump(data, f)

with open("data.pkl", "rb") as f:
loaded = pickle.load(f)

print(loaded)


Выглядит идеально: один модуль, одна строка — и ваш словарь переезжает на диск.

---

### Сильные стороны pickle

1. Работает «из коробки» почти со всем
Списки, словари, множества, пользовательские классы, вложенные структуры — pickle справится.

2. Минимум кода и усилий
Нет нужды вручную описывать поля, типы и схемы.

3. Удобен для быстрых прототипов и кэшей
Например, можно сохранить обученную модель или результат тяжёлых вычислений:

import pickle

class Model:
def __init__(self, weights):
self.weights = weights

model = Model(weights=[0.1, 0.5, 0.9])

with open("model.pkl", "wb") as f:
pickle.dump(model, f)

# ... позже
with open("model.pkl", "rb") as f:
restored_model = pickle.load(f)


---

### Обратная сторона: минусы и подводные камни

1. Опасность безопасности
Главное правило:

> Никогда не делайте pickle.load() на данных из непроверенного источника.

pickle может при десериализации выполнять произвольный код. Это не баг, а особенность протокола.

2. Формат специфичен для Python
Другие языки pickle не понимают. Обмениваться данными с внешними сервисами удобнее через JSON, Protobuf и т.п.

3. Хрупкость к изменению кода
Измените структуру класса — старые .pkl могут перестать корректно загружаться. Для долгосрочного хранения это риск.

4. Бинарный и нечитаемый
Нельзя просто открыть файл в редакторе и «глазами» понять, что внутри.

---

### Когда использовать pickle, а когда — нет?

Подходит:

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

Лучше избегать:

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

---

pickle — это мощный, но «острый» инструмент. Для внутренних задач разработчика он экономит часы работы. Для обмена данными и публичных сервисов чаще всего безопаснее и разумнее выбрать более строгие и переносимые форматы.
👍2🔥2
Создание простого cli-инструмента с аргументами через argparse
Создаём свой первый CLI-инструмент с argparse

Рано или поздно каждый питонист приходит к мысли: «Хочу свою консольную утилиту!» Что‑нибудь, что запускается из терминала, принимает аргументы и делает полезное дело. В Python для этого есть отличный модуль argparse.

---

### Зачем вообще нужны аргументы?

Без аргументов ваш скрипт живёт в режиме «одна команда — один результат». А с аргументами можно:

- менять режим работы (--verbose, --quiet)
- передавать файлы (--input file.txt)
- переключать формат вывода (--json, --text)

И всё это без изменения кода — просто другими параметрами запуска.

---

### Базовый пример: мини-калькулятор

Создадим файл calc.py, который принимает два числа и операцию:

import argparse

def main():
parser = argparse.ArgumentParser(
description="Simple CLI calculator"
)
parser.add_argument("a", type=float, help="First number")
parser.add_argument("b", type=float, help="Second number")
parser.add_argument(
"-o", "--operation",
choices=["add", "sub", "mul", "div"],
default="add",
help="Math operation (default: add)"
)

args = parser.parse_args()

if args.operation == "add":
result = args.a + args.b
elif args.operation == "sub":
result = args.a - args.b
elif args.operation == "mul":
result = args.a * args.b
elif args.operation == "div":
result = args.a / args.b

print(result)

if __name__ == "__main__":
main()


Теперь можно запускать:

python calc.py 2 3
python calc.py 10 5 -o sub
python calc.py 3 4 --operation mul


argparse уже умеет:

- показывать --help с описанием
- проверять типы (type=float)
- ограничивать значения (choices=[...])
- задавать значения по умолчанию (default=)

---

### Пара фишек, которые часто забывают

1. Флаг без значения — просто наличие/отсутствие:

parser.add_argument(
"-v", "--verbose",
action="store_true",
help="Show detailed output"
)


Теперь --verbose даёт args.verbose == True.

2. Переиспользование логики

Лучше выносить «деловую» логику в отдельные функции — тогда скрипт проще тестировать и расширять:

def calculate(a, b, operation):
if operation == "add":
return a + b
if operation == "sub":
return a - b
if operation == "mul":
return a * b
if operation == "div":
return a / b
raise ValueError("Unknown operation")


---

CLI-инструмент в Python — это буквально несколько строк с argparse, а ощущение уже как от «настоящей» утилиты. Попробуйте переписать свой следующий скрипт так, чтобы он принимал аргументы командной строки — разница в удобстве будет огромной.
👍3🔥1
Как работать с постраничной загрузкой данных из API
Python для начинающих: как подружиться с постраничной загрузкой из API

Если вы когда‑нибудь тянули данные из API, то почти наверняка сталкивались с ситуацией: «Тут 10 записей, а где остальные 10 000?». Ответ — в пагинации (postраничной загрузке). API редко отдают всё сразу, чтобы не положить ни себя, ни вас.

Разберёмся, какие бывают схемы пагинации и как с ними работать в Python.

---

### 1. Пагинация по номеру страницы

Классика: у вас есть page и per_page.

import requests

BASE_URL = "https://api.example.com/items"

def fetch_page(page: int, per_page: int = 50):
params = {"page": page, "per_page": per_page}
response = requests.get(BASE_URL, params=params, timeout=10)
response.raise_for_status()
return response.json()

def fetch_all_items():
page = 1
all_items = []
while True:
data = fetch_page(page)
items = data.get("items", [])
if not items:
break
all_items.extend(items)
if not data.get("has_next"): # или проверяем page >= total_pages
break
page += 1
return all_items


Ключевой момент — условие выхода. Часто API возвращает has_next, total_pages или next_page.

---

### 2. Пагинация по смещению (offset/limit)

Тут вам дают offset (сдвиг) и limit (размер пачки):

def fetch_batch(offset: int, limit: int = 100):
params = {"offset": offset, "limit": limit}
response = requests.get(BASE_URL, params=params, timeout=10)
response.raise_for_status()
return response.json()

def fetch_all_items_offset():
offset = 0
limit = 100
all_items = []
while True:
data = fetch_batch(offset, limit)
items = data.get("items", [])
if not items:
break
all_items.extend(items)
offset += limit
return all_items


Минус offset-подхода — при больших объёмах данных он может быть медленнее.

---

### 3. Пагинация по курсору (cursor / next)

Самый «современный» вариант: API возвращает ссылку или токен для следующей страницы.

def fetch_all_items_cursor():
url = BASE_URL
all_items = []
while url:
response = requests.get(url, timeout=10)
response.raise_for_status()
data = response.json()
items = data.get("items", [])
all_items.extend(items)
url = data.get("next") # None, если страниц больше нет
return all_items


Здесь нет ни страниц, ни offset — только next. Это устойчиво к изменениям данных на сервере.

---

### Полезные рекомендации

- Всегда ставьте timeout в requests.get.
- Уважайте лимиты API: иногда нужно делать time.sleep() между запросами.
- Логируйте прогресс: len(all_items) поможет понять, что вы действительно двигаетесь.

Понимая три паттерна пагинации — page, offset, cursor — вы сможете уверенно забирать из API тысячи и миллионы записей, не утонув ни в ошибках, ни в лимитах.
👍3
Работа с форматом YAML в Python с использованием PyYAML
Работа с форматом YAML в Python с использованием PyYAML

YAML любят за читаемость: в отличие от JSON, здесь меньше скобок и больше структуры за счёт отступов. Его часто используют для конфигов, docker-compose, GitHub Actions и т.д. Давайте посмотрим, как работать с YAML в Python с помощью библиотеки PyYAML.

Установка:

pip install pyyaml


---

## Базовая загрузка YAML

Пусть у нас есть файл config.yml:

app:
name: "MyApp"
debug: true
version: 1.0
database:
host: "localhost"
port: 5432
tags:
- primary
- readonly


Прочитаем его:

import yaml

with open("config.yml", "r", encoding="utf-8") as f:
config = yaml.safe_load(f)

print(config["app"]["name"]) # MyApp
print(config["database"]["tags"]) # ['primary', 'readonly']


safe_load — безопасный вариант парсинга, его и стоит использовать почти всегда.

---

## Запись данных в YAML

Сериализуем Python-объекты обратно в YAML:

import yaml

settings = {
"app": {"name": "NewApp", "debug": False},
"features": ["auth", "billing", "reports"]
}

with open("settings.yml", "w", encoding="utf-8") as f:
yaml.safe_dump(settings, f, sort_keys=False, allow_unicode=True)


Параметр sort_keys=False сохраняет порядок ключей, а allow_unicode=True позволяет писать не только ASCII.

---

## Работа со списками и вложенностью

PyYAML без проблем понимает сложные структуры:

import yaml

yaml_str = """
users:
- name: "Alice"
roles: ["admin", "editor"]
- name: "Bob"
roles:
- "viewer"
- "auditor"
"""

data = yaml.safe_load(yaml_str)

admins = [u["name"] for u in data["users"] if "admin" in u["roles"]]
print(admins) # ['Alice']


---

## Кастомные типы через теги

YAML поддерживает теги вроде !MyTag. С их помощью можно превращать YAML-данные сразу в объекты Python.

import yaml
from dataclasses import dataclass

@dataclass
class User:
name: str
level: int

def user_constructor(loader, node):
values = loader.construct_mapping(node)
return User(**values)

yaml.add_constructor("!User", user_constructor)

yaml_str = """
user: !User
name: "Alice"
level: 5
"""

data = yaml.safe_load(yaml_str)
print(data["user"]) # User(name='Alice', level=5)
print(data["user"].level) # 5


Так можно описывать конфиги, которые сразу превращаются в модели вашего приложения.

---

PyYAML — мощный и при этом простой инструмент: он позволяет читать и писать конфиги, работать со сложными структурами и даже маппить YAML на классы Python. Если вы часто имеете дело с настройками и инфраструктурой — эта библиотека станет обязательным пунктом в вашем наборе инструментов.
👍3🔥1
Изучение модуля sched: планирование задач во времени
Изучение модуля sched: планирование задач во времени

Большинство начинающих знают только time.sleep() и думают, что этим инструменты по работе со временем заканчиваются. Но в стандартной библиотеке Python есть модуль sched, который позволяет строить мини-планировщик задач — почти как будильник, но для кода.

### Зачем нужен sched?

sched удобен, когда нужно:

- выполнить задачу через некоторое время;
- запланировать серию событий;
- управлять порядком выполнения задач во времени.

При этом он не блокирует весь код сам по себе — вы сами решаете, когда запустить обработку событий.

### Базовый пример

import sched
import time

scheduler = sched.scheduler(time.time, time.sleep)

def say_hello(name):
print(f"Hello, {name}! Time:", time.time())

print("Start:", time.time())
scheduler.enter(3, 1, say_hello, argument=("Alice",))
scheduler.run()
print("End:", time.time())


Что здесь происходит:

- sched.scheduler(time.time, time.sleep) — создаем планировщик, который знает «что такое сейчас» и «как подождать».
- enter(delay, priority, action, argument=...) — выполняет action через delay секунд.
- scheduler.run() — запускает цикл обработки событий (блокирует поток до выполнения всех задач).

Через 3 секунды вы увидите приветствие и текущий timestamp.

### Приоритеты и несколько задач

priority пригодится, когда два события должны выполниться в одно и то же время.

import sched
import time

scheduler = sched.scheduler(time.time, time.sleep)

def log(msg):
print(time.time(), msg)

scheduler.enter(5, 2, log, argument=("low priority",))
scheduler.enter(5, 1, log, argument=("high priority",))

scheduler.run()


Обе задачи запланированы через 5 секунд, но сначала выполнится та, у которой priority=1.

### Отложенные и повторяющиеся задачи

Повторения можно организовать вручную — внутри функции заново планировать саму себя:

import sched
import time

scheduler = sched.scheduler(time.time, time.sleep)

def periodic_task(interval):
print("Tick at", time.time())
scheduler.enter(interval, 1, periodic_task, argument=(interval,))

scheduler.enter(1, 1, periodic_task, argument=(2,))
scheduler.run()


Здесь первая задача стартует через 1 секунду, а затем каждые 2 секунды перепланирует себя.

### Когда использовать sched, а когда нет

sche­d хорош для:

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

Если нужно:

- сложное расписание (крон-подобное);
- работа с разными часовыми поясами, датами, календарями;
- продвинутая асинхронность,

то лучше посмотреть в сторону APScheduler, asyncio или системного cron.

Но для понимания базовых принципов планирования задач во времени sched — идеальный старт, да еще и без сторонних библиотек.
👍4
Инструменты отладки кода: использование модуля pdb
Инструменты отладки кода: знакомство с модулем pdb

Большинство новичков отлаживают код методом «print по всему файлу». Это работает, пока проект маленький. Но как только логика усложняется, принты превращают код в хаос. Пора знакомиться с встроенным отладчиком Python — модулем pdb.

---

## Что такое pdb и зачем он нужен

pdb позволяет:
- ставить точки останова (breakpoints);
- пошагово выполнять код;
- смотреть значения переменных «изнутри» функции;
- менять состояние программы на лету.

И все это — прямо в терминале, без IDE.

---

## Базовый пример: pdb.set_trace()

Допустим, у нас странная функция, которая считает среднее, но иногда падает с ошибкой:

import pdb

def avg(values):
total = 0
count = 0
for v in values:
total += v
count += 1
return total / count

data = [10, 20, 0, "oops", 40]

pdb.set_trace() # точка останова
result = avg(data)
print(result)


Запускаем:

python script.py


На строке с set_trace() программа остановится, и вы увидите приглашение вида:

(Pdb)


Теперь можно управлять выполнением.

---

## Минимальный набор команд pdb

Внутри отладчика доступны команды:

- l — (list) показать код вокруг текущей строки;
- n — (next) выполнить следующую строку в текущей функции;
- s — (step) шаг внутрь вызываемой функции;
- c — (continue) продолжить выполнение до следующего breakpoint;
- p expr — (print) напечатать выражение, например p data;
- q — (quit) выйти из отладчика.

Например, из нашего примера:

(Pdb) p data
[10, 20, 0, 'oops', 40]
(Pdb) n


Можно зайти внутрь avg:

(Pdb) s


И уже там:

(Pdb) p v
10
(Pdb) n
(Pdb) p total
10


Так легко найти момент, когда v внезапно становится строкой "oops" и ломает вычисления.

---

## Breakpoint без импорта: встроенная функция breakpoint()

Начиная с Python 3.7 есть удобный шорткат:

def calc_sum(values):
s = 0
for v in values:
s += v
return s

data = [1, 2, 3]
breakpoint() # работает как pdb.set_trace() по умолчанию
print(calc_sum(data))


Функция breakpoint() смотрит на переменную окружения PYTHONBREAKPOINT, поэтому при желании можно подменять стандартный отладчик.

---

## Отладка конкретного файла через -m pdb

Иногда не хочется править код и вставлять set_trace(). Можно запустить файл целиком через pdb:

python -m pdb script.py


pdb сразу загрузит файл, поставит breakpoint на первой строке, и дальше вы будете управлять выполнением командами n, s, c и т.д.

---

pdb — это минимальный, но мощный инструмент, который стоит освоить как можно раньше. Он дисциплинирует мышление: вместо хаотичных принтов вы начинаете осознанно исследовать состояние программы и понимать, почему она ведет себя так, а не иначе.
3👍1
Как работать с цветом в терминале: библиотека colorama
Как работать с цветом в терминале: библиотека colorama

Текстовый вывод в консоль необязательно должен быть скучным. Цвет помогает выделять ошибки, предупреждения, важные шаги и просто делает скрипт понятнее. В Python это удобно делать с помощью библиотеки colorama.

---

## Установка и базовое использование

Установим библиотеку:

pip install colorama


Минимальный пример:

from colorama import init, Fore, Back, Style

init(autoreset=True)

print(Fore.RED + "Error: something went wrong")
print(Fore.GREEN + "Success: all tests passed")
print(Back.YELLOW + Fore.BLACK + "Warning: check your settings")
print(Style.DIM + "This is a dim text")
print(Style.BRIGHT + "This is a bright text")


init(autoreset=True) автоматически сбрасывает цвет после каждой строки, чтобы не красить весь терминал случайно.

---

## Ручной контроль сброса

Если нужно более тонко управлять стилем:

from colorama import init, Fore, Style

init(autoreset=False)

print(Fore.CYAN + "Step 1:", Style.RESET_ALL, "download data")
print(Fore.MAGENTA + "Step 2:", Style.RESET_ALL, "process data")

print(Fore.RED + "Critical message", end="")
print(Style.RESET_ALL) # сбросили только здесь


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

---

## Цветной логгер своими руками

Сделаем простой цветной вывод по уровням:

from colorama import init, Fore, Style

init(autoreset=True)

def log(message, level="info"):
if level == "info":
color = Fore.CYAN
elif level == "warning":
color = Fore.YELLOW
elif level == "error":
color = Fore.RED + Style.BRIGHT
else:
color = Fore.WHITE

print(color + f"[{level.upper()}] {message}")

log("Application started", "info")
log("Low disk space", "warning")
log("Unable to connect to database", "error")


Такой мини-логгер уже заметно улучшает читаемость вывода, особенно в длинных скриптах.

---

## Кроссплатформенность

Главный плюс colorama — он одинаково работает:

- на Windows (преобразует ANSI-коды в понятные для консоли команды),
- в Linux и macOS (где ANSI уже поддерживаются).

То есть вы один раз пишете цветной вывод — и не думаете о том, на какой системе будет запускаться ваш скрипт.

---

Попробуйте добавить colorama в свои маленькие утилиты: подсветите ошибки, выделите успешные шаги, сделайте прогресс более наглядным. Цвет в консоли — это простой инструмент, который заметно повышает удобство работы с программой.
👍5
Парсинг командной строки с помощью модулей getopt и argparse
Парсинг командной строки с помощью getopt и argparse

Когда скрипт перестаёт быть «одноразовым файлом» и превращается в инструмент, ему срочно нужны параметры командной строки. Флаги вроде --input data.csv или -v делают ваш код удобным, автоматизируемым и… чуть менее хаотичным.

В Python для этого исторически есть два модуля: «олдскульный» getopt и современный, почти стандарт де-факто — argparse.

---

## getopt: минимализм в стиле POSIX

getopt напоминает классический getopt из C. Он прост, если вам нужны только короткие флаги и немного логики.

import sys
import getopt

def main():
short_opts = "hi:o:"
long_opts = ["help", "input=", "output="]

try:
opts, args = getopt.getopt(sys.argv[1:], short_opts, long_opts)
except getopt.GetoptError as err:
print(err)
sys.exit(2)

input_file = None
output_file = None

for opt, val in opts:
if opt in ("-h", "--help"):
print("Usage: script.py -i <input> -o <output>")
sys.exit()
elif opt in ("-i", "--input"):
input_file = val
elif opt in ("-o", "--output"):
output_file = val

print("Input:", input_file)
print("Output:", output_file)
print("Positional args:", args)

if __name__ == "__main__":
main()


Плюсы: минимальные зависимости и поведение, знакомое по Unix.
Минусы: вручную писать help, валидировать значения, обрабатывать ошибки.

---

## argparse: когда хочется «по-взрослому»

argparse создаёт полноценный CLI почти без лишнего кода: автоматический --help, валидация типов, значения по умолчанию, подкоманды.

import argparse

def main():
parser = argparse.ArgumentParser(
description="Resize image with given scale"
)
parser.add_argument("path", help="Path to image file")
parser.add_argument("-s", "--scale", type=float, default=1.0,
help="Resize scale (default: 1.0)")
parser.add_argument("-v", "--verbose", action="store_true",
help="Enable verbose output")

args = parser.parse_args()

if args.verbose:
print(f"Loading image from {args.path}")
print(f"Scale factor: {args.scale}")

# here could be real image processing
print("Resized successfully")

if __name__ == "__main__":
main()


Запустите:

python script.py photo.jpg -s 0.5 -v
python script.py --help


argparse сам:
- разберёт параметры,
- покажет аккуратный help,
- выдаст понятную ошибку, если аргументы неверны.

---

### Что выбрать?

- Небольшие утилиты, где нужен лишь парочка флагов и вы любите POSIX-стиль — можно getopt.
- Любой скрипт, который должны читать и использовать другие люди (а часто и вы сами через месяц) — однозначно argparse.

Если ваш Python-скрипт ещё запускается как python script.py без параметров — самое время превратить его в инструмент, а не в лотерею с input() и захардкоженными путями.
👍31
Создание прогресс-бара в терминале с использованием tqdm
### Python для начинающих: создаем красивый прогресс-бар с tqdm

Когда скрипт «думает» дольше пары секунд, пользователь начинает волноваться: «Он вообще работает или уже завис?». Прогресс-бар в терминале решает эту проблему — и модуль tqdm делает это буквально одной строкой кода.

---

## Установка

tqdm не входит в стандартную библиотеку, его нужно установить:

pip install tqdm


---

## Базовый пример

Минимальный прогресс-бар для цикла:

from time import sleep
from tqdm import tqdm

for i in tqdm(range(100)):
sleep(0.05) # имитация работы


Что происходит:
- tqdm(iterable) оборачивает любой итерируемый объект (range, список, генератор);
- выводит прогресс, процент, скорость и время до окончания.

---

## Прогресс-бар для списков и генераторов

tqdm не требует именно range. Можно использовать списки:

from time import sleep
from tqdm import tqdm

files = ["data1.csv", "data2.csv", "data3.csv"]

for filename in tqdm(files, desc="Processing"):
sleep(0.5) # обработка файла


Аргумент desc добавляет понятное описание слева от прогресс-бара.

---

## Ручное обновление прогресса

Если у вас нет удобного итератора (например, цикл внутри функции), можно обновлять прогресс вручную:

from time import sleep
from tqdm import tqdm

total_steps = 5

with tqdm(total=total_steps, desc="Custom task") as pbar:
for step in range(total_steps):
sleep(0.7) # тяжелая операция
pbar.update(1)


Здесь:
- total — общее количество шагов;
- pbar.update(n) — сообщаем, что выполнено n шагов.

---

## Обёртка для функций: tqdm + map

Если вы обрабатываете коллекцию с помощью map, можно добавить прогресс почти без изменений кода:

from time import sleep
from tqdm import tqdm

def process_item(item):
sleep(0.2)
return item * 2

items = list(range(50))
results = list(tqdm(map(process_item, items), total=len(items)))


Важный момент: для map нужно явно указать total=len(items), иначе tqdm не знает, сколько всего элементов.

---

## Быстрый чек-лист по tqdm

- Подходит для любых итерируемых объектов.
- Умеет считать время, скорость и ETA.
- Можно использовать как контекстный менеджер и обновлять вручную.
- Практически не требует изменений логики программы.

Попробуйте добавить tqdm в ваш текущий скрипт с долгими циклами — и терминал сразу станет дружелюбнее для пользователя… и для вас.
👍4🔥1