Python для начинающих
1.24K subscribers
546 photos
3 videos
232 files
74 links
Python для начинающих
Download Telegram
Основы работы с очередями задач: библиотека RQ
Python для начинающих: основы работы с очередями задач и библиотекой RQ

Если ваш скрипт регулярно делает «тяжелые» вещи — обрабатывает изображения, шлет письма, дергает внешние API, — рано или поздно вы упретесь в задержки. Пользователь кликает кнопку, а страница «думает» 10 секунд. Некрасиво.

Выход — вынести тяжелую работу в фоновую очередь задач. Одна из самых простых библиотек для этого в Python — RQ (Redis Queue).

---

### Что такое RQ в двух словах

RQ — это:
- Redis как хранилище очередей;
- worker-процессы, которые забирают задачи из очереди;
- декоратор или функция enqueue, чтобы отправить задачу в фон.

Схема проста: ваш веб-код быстро ставит задачу в очередь и сразу отвечает пользователю, а worker спокойно делает работу «за кулисами».

---

### Установка и базовый пример

Устанавливаем:

pip install rq redis


Нужен запущенный Redis-сервер.

Пусть у нас есть файл tasks.py:

# tasks.py
import time

def process_file(file_path: str) -> str:
print(f"Start processing {file_path}")
time.sleep(5) # heavy work imitation
return f"Processed: {file_path}"


Теперь добавим задачу в очередь:

# enqueue_task.py
from redis import Redis
from rq import Queue
from tasks import process_file

redis_conn = Redis()
q = Queue("default", connection=redis_conn)

job = q.enqueue(process_file, "/tmp/data.csv")
print("Job ID:", job.id)


Запускаем worker:

rq worker default


Worker подключится к Redis, увидит задачу и выполнит process_file в фоне.

---

### Проверка состояния задачи

RQ позволяет отслеживать статус:

from rq import Queue
from rq.job import Job
from redis import Redis

redis_conn = Redis()
q = Queue("default", connection=redis_conn)

job = Job.fetch("your-job-id", connection=redis_conn)
print(job.get_status()) # queued, started, finished, failed
print(job.result) # результат после выполнения


---

### Почему это удобно

- Не блокируете основной поток (веб-запрос, CLI-интерфейс).
- Легко масштабировать: просто запускаете больше worker-процессов.
- Простая интеграция с Flask/Django: вместо «сделать сейчас» — q.enqueue(...).

Для начала работы с фоновыми задачами RQ — отличный инструмент: минимум магии, максимум понятности. Попробуйте вынести в очередь все, что занимает больше пары секунд, и вы увидите, насколько живее станет ваше приложение.
🔥3👍1
Как использовать модули math и decimal для точных вычислений
Как использовать модули math и decimal для точных вычислений

Новички в Python часто удивляются: почему 0.1 + 0.2 != 0.3? Компьютер ведь «строго математичный»… но нет. Виновата двоичная плавающая точка: не все десятичные дроби могут быть точно представлены в памяти.

Сегодня разберёмся, когда достаточно модуля math, а когда нужно доставать тяжёлую артиллерию — decimal.

---

## Модуль math: быстро и по-научному

math работает с типом float. Он быстрый, удобный и идеально подходит для:

- тригонометрии;
- корней, логарифмов;
- работы с константами (pi, e).

import math

radius = 2.5
circle_area = math.pi * radius ** 2
print(circle_area) # 19.634954084936208

x = 0.5
print(math.sin(x), math.log(x), math.sqrt(x))


Погрешности здесь небольшие и в научных расчётах обычно приемлемые.

---

## Где float подводит

В финансовых и бухгалтерских задачах ошибка в 0.01 уже критична.

price = 0.1
total = price * 3
print(total) # 0.30000000000000004
print(total == 0.3) # False


Человек видит 0.3, компьютер — нет. Для денег и точных десятичных значений нужен decimal.

---

## Модуль decimal: точные деньги и не только

decimal.Decimal хранит число как десятичное, а не двоичное представление.

from decimal import Decimal

price = Decimal("0.1")
total = price * 3
print(total) # 0.3
print(total == Decimal("0.3")) # True


Ключевой момент — создавать Decimal из строки, а не из float, иначе потащите с собой уже округлённую двоичную ошибку.

---

## Управление точностью через контекст

decimal позволяет настраивать точность и режимы округления.

from decimal import Decimal, getcontext

getcontext().prec = 6 # количество значащих цифр

x = Decimal("1") / Decimal("7")
print(x) # 0.142857

getcontext().prec = 28
y = Decimal("1") / Decimal("7")
print(y) # 0.1428571428571428571428571429


Можно выбирать и стратегию округления (например, банковское округление), что критично для расчёта налогов, процентов, комиссий.

---

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

- math + float
Физика, геометрия, машинное обучение, игры — где микропогрешности не страшны, а скорость важнее.

- decimal
Деньги, пересчёт валют, бухгалтерия, точные отчёты — там, где каждая копейка на счету.

Если у вас в задаче фигурируют «рубли», «копейки», «проценты по кредиту» — почти наверняка нужен decimal. Если «угол», «скорость», «синус» — смело берите math.
4👍1
Чтение и модификация PDF с помощью PyPDF2
Чтение и модификация PDF с помощью PyPDF2

PDF‑файлы часто кажутся чем-то «закрытым»: удобно читать, сложно менять. Но в Python есть библиотека, которая ломает этот миф, — PyPDF2. С ее помощью можно собирать отчеты из нескольких файлов, вытаскивать текст, разбирать документы по страницам и даже ставить водяные знаки.

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

pip install pypdf2


---

### Чтение PDF и извлечение текста

Начнем с базового: как прочитать PDF и вытащить из него текст.

from PyPDF2 import PdfReader

reader = PdfReader("report.pdf")
print("Pages:", len(reader.pages))

page_0 = reader.pages[0]
text = page_0.extract_text()
print(text)


Важно: извлечение текста зависит от структуры PDF. В нормально сформированных документах работает отлично, а вот сканы без распознавания текста будут пустыми — там нужен уже OCR (например, Tesseract), а не PyPDF2.

---

### Объединение нескольких PDF

Представьте, что нужно склеить несколько отчетов в один общий файл:

from PyPDF2 import PdfMerger

merger = PdfMerger()
files = ["intro.pdf", "chapter1.pdf", "chapter2.pdf"]

for file_name in files:
merger.append(file_name)

merger.write("full_report.pdf")
merger.close()


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

---

### Разделение PDF по страницам

Теперь наоборот: нужно разрезать большой PDF на отдельные файлы, по странице в каждом.

from PyPDF2 import PdfReader, PdfWriter

reader = PdfReader("big_document.pdf")

for i, page in enumerate(reader.pages):
writer = PdfWriter()
writer.add_page(page)
output_name = f"page_{i + 1}.pdf"
with open(output_name, "wb") as output_file:
writer.write(output_file)


Так удобно разбивать сканы документов, договоры, длинные инструкции.

---

### Водяной знак на каждую страницу

Частая задача — пометить документ водяным знаком «Confidential»:

from PyPDF2 import PdfReader, PdfWriter

base_reader = PdfReader("original.pdf")
watermark_reader = PdfReader("watermark.pdf")

watermark_page = watermark_reader.pages[0]
writer = PdfWriter()

for page in base_reader.pages:
page.merge_page(watermark_page)
writer.add_page(page)

with open("watermarked.pdf", "wb") as output_file:
writer.write(output_file)


Файл watermark.pdf — это обычная страница с текстом/логотипом, заранее подготовленная в любом редакторе.

---

PyPDF2 — отличный инструмент, чтобы перестать воспринимать PDF как «нередактируемый камень». С его помощью легко автоматизировать отчеты, подготовку документов, рассылки и архивирование — прямо из вашего кода на Python.
👍5
Использование библиотеки tabulate для красивого вывода таблиц
Использование библиотеки tabulate для красивого вывода таблиц

Когда выводишь данные в консоль обычными print, быстро наступает хаос: всё съезжает, столбцы пляшут, читать неудобно. Библиотека tabulate решает это за нас — она превращает списки и словари в аккуратные таблицы в одну строку кода.

---

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

pip install tabulate


И можно начинать.

---

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

from tabulate import tabulate

data = [
["Alice", 23, "Engineer"],
["Bob", 31, "Designer"],
["Charlie", 27, "Developer"],
]

headers = ["Name", "Age", "Job"]

print(tabulate(data, headers=headers))


Результат будет вроде:

Name      Age  Job
------- ---- ----------
Alice 23 Engineer
Bob 31 Designer
Charlie 27 Developer


Без ручного выравнивания — всё красиво само.

---

### Разные форматы таблиц

tabulate умеет множество стилей: "grid", "fancy_grid", "github", "pipe", "pretty" и др.

from tabulate import tabulate

data = [
["Book", 12.5],
["Pen", 1.2],
["Notebook", 3.99],
]

headers = ["Item", "Price"]

print(tabulate(data, headers=headers, tablefmt="grid"))
print()
print(tabulate(data, headers=headers, tablefmt="github"))


Можно подобрать стиль под задачу: для документации — "github", для наглядности в консоли — "grid" или "fancy_grid".

---

### Работа со словарями

Необязательно собирать данные в списки — можно использовать списки словарей.

from tabulate import tabulate

users = [
{"name": "Alice", "score": 95},
{"name": "Bob", "score": 87},
{"name": "Charlie", "score": 92},
]

print(tabulate(users, headers="keys", tablefmt="fancy_grid"))


headers="keys" говорит: взять ключи словарей как названия столбцов.

---

### Выравнивание и формат чисел

Числа часто хочется выровнять по правому краю и красиво отформатировать.

from tabulate import tabulate

data = [
["USD", 1.0],
["EUR", 0.93],
["JPY", 147.25],
]

headers = ["Currency", "Rate"]

print(tabulate(
data,
headers=headers,
tablefmt="github",
floatfmt=".2f", # два знака после запятой
colalign=("left", "right"), # выравнивание столбцов
))


---

tabulate — идеальный помощник, когда нужно быстро привести данные в понятный вид: логи, результаты скриптов, небольшие отчёты. Одна строка — и у вас уже «мини-Excel» прямо в терминале.
👍5
Создание простого файлового менеджера на консоли
Создаем простой консольный файловый менеджер на Python

Файловый менеджер — отличный мини-проект для прокачки работы с файловой системой, модуля os и аргументами командной строки. Без GUI, только консоль и код.

Идея: написать скрипт, который умеет:

- показывать текущую папку и её содержимое
- переходить по каталогам
- создавать и удалять файлы/папки
- копировать и переименовывать файлы

Основные инструменты:

- os — работа с путями и директориями
- shutil — копирование и перемещение
- sys.argv — обработка команд, переданных при запуске

---

### Структура команд

Сделаем формат:

python fm.py ls
python fm.py cd new_folder
python fm.py touch notes.txt
python fm.py rm notes.txt
python fm.py mkdir projects
python fm.py cp src.txt backup.txt
python fm.py mv old.txt new.txt


Теперь реализуем ядро менеджера.

import os
import sys
import shutil

def list_dir():
print("Current dir:", os.getcwd())
for name in os.listdir():
mark = "/" if os.path.isdir(name) else ""
print(f"- {name}{mark}")

def change_dir(path):
try:
os.chdir(path)
print("Changed dir to:", os.getcwd())
except FileNotFoundError:
print("Path not found")

def make_file(name):
if os.path.exists(name):
print("File already exists")
return
with open(name, "w", encoding="utf-8") as f:
pass
print("File created:", name)

def remove_path(path):
if os.path.isdir(path):
shutil.rmtree(path)
print("Directory removed:", path)
elif os.path.isfile(path):
os.remove(path)
print("File removed:", path)
else:
print("Nothing to remove")

def make_dir(name):
os.makedirs(name, exist_ok=True)
print("Directory created:", name)

def copy_file(src, dst):
if not os.path.isfile(src):
print("Source file not found")
return
shutil.copy2(src, dst)
print(f"Copied {src} -> {dst}")

def move_file(src, dst):
if not os.path.exists(src):
print("Source not found")
return
shutil.move(src, dst)
print(f"Moved {src} -> {dst}")

def main():
if len(sys.argv) < 2:
print("Usage: fm.py [ls|cd|touch|rm|mkdir|cp|mv] ...")
return

cmd = sys.argv[1]
args = sys.argv[2:]

if cmd == "ls":
list_dir()
elif cmd == "cd" and args:
change_dir(args[0])
elif cmd == "touch" and args:
make_file(args[0])
elif cmd == "rm" and args:
remove_path(args[0])
elif cmd == "mkdir" and args:
make_dir(args[0])
elif cmd == "cp" and len(args) == 2:
copy_file(args[0], args[1])
elif cmd == "mv" and len(args) == 2:
move_file(args[0], args[1])
else:
print("Unknown or invalid command")

if __name__ == "__main__":
main()


---

Что можно улучшить дальше:

- добавить цветной вывод (colorama)
- историю команд
- безопасное удаление (перемещение в «корзину»)
- конфиг с «домашней» директорией

Такой мини-проект одновременно тренирует работу с модулями, аргументами, обработкой ошибок и структурой кода — идеальный шаг от учебных задачек к реальным утилитам.
👍5🔥1
Построение простой системы рекомендаций на основе анализа покупок
Построение простой системы рекомендаций на основе покупок

Представим, что у нас есть небольшой онлайн‑магазин, и мы хотим показывать покупателю блок «С этим товаром часто покупают». Звучит как магия, но на базовом уровне это можно сделать несколькими строками кода на Python.

Базовая идея:
если товары A и B часто встречаются в одной корзине, то покупателям товара A можно рекомендовать B (и наоборот).

### Данные

Допустим, у нас есть список заказов, и каждый заказ — это набор купленных товаров:

transactions = [
["milk", "bread", "eggs"],
["bread", "butter"],
["milk", "bread"],
["beer", "chips"],
["beer", "chips", "nuts"],
["milk", "eggs"],
]


### Считаем совместные покупки

Используем collections.Counter, чтобы посчитать, какие пары товаров встречаются вместе чаще всего:

from collections import Counter
from itertools import combinations

pair_counter = Counter()

for basket in transactions:
# все уникальные пары товаров из одной корзины
for item1, item2 in combinations(sorted(set(basket)), 2):
pair_counter[(item1, item2)] += 1

print(pair_counter.most_common(5))


Так мы получаем «рейтинг дружбы» товаров: чем больше счётчик, тем чаще товары покупают вместе.

### Строим простые рекомендации

Сделаем функцию, которая по товару отдаёт список рекомендаций:

from collections import defaultdict

def build_recommendations(pair_counter, min_support=1):
related = defaultdict(list)
for (item1, item2), count in pair_counter.items():
if count < min_support:
continue
related[item1].append((item2, count))
related[item2].append((item1, count))
# сортируем по популярности совместной покупки
for item in related:
related[item].sort(key=lambda x: x[1], reverse=True)
return related

recommendations = build_recommendations(pair_counter, min_support=1)

def recommend_for(item, top_n=3):
return [x for x, _ in recommendations.get(item, [])[:top_n]]

print("For 'milk':", recommend_for("milk"))
print("For 'beer':", recommend_for("beer"))


Теперь для любого товара мы можем быстро получить список «часто покупаемых вместе».

### Что можно улучшить

1. Учесть частоту самого товара — нормировать по общему числу покупок товара (меры вроде lift, confidence).
2. Фильтровать редкие пары с помощью min_support, чтобы не советовать то, что встретилось один раз случайно.
3. Сохранить модель (словарь recommendations) в файл через json или pickle и подгружать в вашем веб‑приложении.

Это ещё не «умный» AI, но уже рабочая рекомендательная система, которую легко встроить в учебный проект интернет‑магазина и постепенно усложнять: добавлять веса, категории, сезонность и, конечно, больше данных.
👍41
Работа с переводом и интернационализацией: модуль gettext на примерах
Python для начинающих: перевод и интернационализация с модулем gettext

Когда приложение начинает жить дольше пары недель, внезапно выясняется: пользователи не обязаны знать английский. А переписывать все строки под каждый язык — боль. Для этого в Python есть стандартный модуль gettext, который превращает ваш код в многоязычную машину.

---

## Базовая идея

Вы пишете код один раз, помечая фразы для перевода. Реальные тексты для разных языков хранятся в отдельных файлах. Программа выбирает нужный язык «на лету».

Классический паттерн:

import gettext

lang = gettext.translation(
domain="messages",
localedir="locale",
languages=["es"], # например, испанский
fallback=True
)
lang.install()
_ = lang.gettext # сокращение

print(_("Hello, world!"))


Если есть перевод, на экране окажется что-то вроде Hola, mundo!. Если нет — исходная фраза.

---

## Структура проекта

Сделаем минимальный каркас:

project/
app.py
locale/
es/
LC_MESSAGES/
messages.po
messages.mo


domain="messages" → имя файла переводов messages.po/.mo.
localedir="locale" → корневая папка с переводами.
languages=["es"] → нужный язык (ISO-код).

---

## Подготовка шаблона переводов

В коде достаточно помечать строки через _():

# app.py
import gettext

gettext.bindtextdomain("messages", "locale")
gettext.textdomain("messages")
_ = gettext.gettext

user_name = "Alex"
print(_("Welcome, {user}!").format(user=user_name))
print(_("Exit"))


Далее нужно сгенерировать список фраз. Обычно это делается внешней утилитой xgettext, но принцип такой:

1. Собираем все строки внутри _("") в шаблон .pot.
2. Для каждого языка создаём .po.
3. Компилируем .po в .mo.

Пример содержимого messages.po (упрощённо):

msgid "Welcome, {user}!"
msgstr "¡Bienvenido, {user}!"

msgid "Exit"
msgstr "Salir"


После компиляции (через msgfmt или инструменты IDE) появится messages.mo, который читает gettext.

---

## Плюс форматирования: не ломаем код

Важно не «убивать» форматирование строк. Вы можете смело использовать format() или f-строки, главное — сохранять имена плейсхолдеров:

msg = _("You have {count} new message(s).").format(count=5)
print(msg)


В переводе:

msgid "You have {count} new message(s)."
msgstr "У вас {count} новых сообщений."


---

## Переключение языка на лету

Вы можете дать пользователю выбор:

import gettext

def get_translator(lang_code):
translation = gettext.translation(
"messages",
localedir="locale",
languages=[lang_code],
fallback=True
)
return translation.gettext

lang_code = "es" # например, пришло из настроек
_ = get_translator(lang_code)

print(_("Settings"))
print(_("Profile"))


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

---

gettext — это не магия, а аккуратное разделение текста и логики. Один раз настроили структуру и процесс генерации .po/.mo — и дальше добавление нового языка сводится к переводу строк, без переписывания кода.
👍6
Простое создание QR-кодов с помощью qrcode: как закодировать информацию
Простое создание QR-кодов с помощью qrcode: как закодировать информацию

QR-коды давно вышли из мира маркетинга и стали удобным способом быстро передавать ссылки, Wi‑Fi‑пароли, визитки и любую короткую текстовую информацию. А с Python сделать свой QR-код можно буквально в несколько строк.

---

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

Для начала установим библиотеку:

pip install qrcode[pil]


[pil] добавляет поддержку изображений через Pillow, чтобы сразу сохранять QR-код в PNG/JPEG.

---

## Самый простой QR-код

Сделаем QR-код с ссылкой:

import qrcode

data = "https://python.org"

img = qrcode.make(data)
img.save("python_org_qr.png")


Готово: python_org_qr.png можно открыть, распечатать или вставить в презентацию.

---

## Больше контроля: размер, цвет, ошибка

Для тонкой настройки используем класс QRCode:

import qrcode
from qrcode.constants import ERROR_CORRECT_H

qr = qrcode.QRCode(
version=2, # размер: 1–40 (чем больше, тем больше данных)
error_correction=ERROR_CORRECT_H, # до ~30% восстановления
box_size=8, # размер "квадратика" в пикселях
border=4, # рамка (минимум 4)
)

qr.add_data("WiFi password: MySecretPass123")
qr.make(fit=True)

img = qr.make_image(fill_color="black", back_color="white")
img.save("wifi_qr.png")


Параметр error_correction важен, если QR-код будут печатать маленьким или частично закрывать (наклейка, логотип). Уровень ERROR_CORRECT_H даст максимальный шанс всё равно считать код.

---

## Закодируем виртуальную визитку

QR-код может содержать не только ссылки, но и, например, vCard:

import qrcode

vcard = """BEGIN:VCARD
VERSION:3.0
N:Smith;John;;;
FN:John Smith
EMAIL:john@example.com
TEL:+123456789
END:VCARD
"""

img = qrcode.make(vcard)
img.save("vcard_qr.png")


Смартфон при сканировании предложит сохранить контакт сразу в адресную книгу.

---

## Идеи для применения

- Быстрый доступ к документации проекта.
- Генерация бэджей участников мероприятия.
- Маркировка оборудования: QR-код с номером и ссылкой на карточку в системе учёта.
- Генерация временных ссылок и токенов в админ-интерфейсе.

QR-коды — отличный пример того, как несколько строк Python превращаются в инструмент, который можно применить и в проектах, и в реальной «офлайновой» жизни.
👍3
Модуль pathlib: современная работа с файловой системой
Модуль pathlib: современная работа с файловой системой

Если вы всё ещё склеиваете пути к файлам через os.path и плюсики — самое время познакомиться с pathlib. Это «современный» способ работы с путями в Python: объектно-ориентированный, удобный и кроссплатформенный.

---

### Зачем нужен pathlib

pathlib решает несколько болезненных мест:

- Не нужно думать о слэше: / под Linux и \ под Windows.
- Пути становятся объектами, а не строками.
- Методы для чтения/записи файлов встроены прямо в объект пути.

Подключение модуля:

from pathlib import Path


---

### Создание и комбинирование путей

from pathlib import Path

base_dir = Path.home() # Домашняя папка пользователя
project_dir = base_dir / "my_project" / "data" # Склеивание через /

print(project_dir)
print(project_dir.exists()) # Проверяем, существует ли путь
print(project_dir.is_dir()) # Это папка?


Оператор / перегружен и безопасно соединяет части пути с учётом ОС.

---

### Поиск файлов по маске

Найдем все .txt в директории:

data_dir = Path("data")

for txt_file in data_dir.glob("*.txt"):
print(txt_file.name, txt_file.stat().st_size, "bytes")


glob() поддерживает маски (*, **) и позволяет быстро обходить дерево каталогов.

---

### Чтение и запись файлов

Необязательно открывать файл через open:

file_path = Path("data") / "notes.txt"

# Запись текста
file_path.write_text("Hello, pathlib!\nSecond line.")

# Чтение текста
content = file_path.read_text()
print(content)


Есть и бинарные варианты: write_bytes() и read_bytes().

---

### Создание директорий и безопасная работа

logs_dir = Path("logs")
logs_dir.mkdir(exist_ok=True, parents=True) # Создаст все недостающие папки

log_file = logs_dir / "app.log"

if not log_file.exists():
log_file.write_text("Log start\n")
else:
with log_file.open("a", encoding="utf-8") as f:
f.write("New log line\n")


parents=True создаст всю цепочку директорий, а exist_ok=True не вызовет ошибку, если папка уже есть.

---

### Абсолютные пути и нормализация

p = Path("data") / ".." / "data" / "file.txt"
print(p) # Относительный "кривой" путь
print(p.resolve()) # Нормализованный абсолютный путь


resolve() приводит путь к каноничному виду и показывает, куда он реально ведет.

---

pathlib хорошо ложится на мышление «объект пути + действия с ним», избавляя от ручной возни со строками. Если вы начинаете с Python сегодня — имеет смысл сразу привыкать именно к такому стилю работы с файловой системой.
👍3
Как использовать модуль statistics для вычислений: среднее, медиана и мода
Как использовать модуль statistics: среднее, медиана и мода без боли в мозге

Когда вы считаете средние оценки, анализируете продажи или смотрите на результаты эксперимента — без базовой статистики далеко не уедешь. В Python для этого есть готовый инструмент — модуль statistics. Он избавляет от самописных циклов и формул и помогает считать всё в одну строку.

---

## Подготовка

Модуль встроен в стандартную библиотеку, поэтому никаких установок не нужно:

import statistics as stats


Для примеров возьмём список чисел:

data = [10, 12, 13, 15, 15, 17, 18]


---

## Среднее (mean)

Среднее арифметическое — сумма всех значений, делённая на их количество. В statistics это делается так:

import statistics as stats

data = [10, 12, 13, 15, 15, 17, 18]
avg = stats.mean(data)
print(avg) # 14.285714285714286


Круто то, что модуль сам обрабатывает int и float, не нужно думать о типах.

---

## Медиана (median)

Медиана — это «середина» отсортированных данных. Она устойчивее к выбросам. Если в выборке внезапно появится «сумасшедшее» значение, среднее уедет, а медиана — почти нет.

import statistics as stats

data = [10, 12, 13, 1000] # явный выброс
mean_value = stats.mean(data)
median_value = stats.median(data)

print(mean_value) # 258.75
print(median_value) # 12.5


Медиана сразу показывает, что «нормальные» значения всё ещё где-то около 12–13, а не 258.75.

---

## Мода (mode)

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

import statistics as stats

grades = [5, 4, 5, 3, 4, 5, 5, 4]
most_common = stats.mode(grades)
print(most_common) # 5


Важно: если в данных несколько значений с одинаковой максимальной частотой, mode() в некоторых версиях Python может выбросить StatisticsError. Для таких случаев есть более гибкая функция multimode():

import statistics as stats

values = [1, 2, 2, 3, 3]
modes = stats.multimode(values)
print(modes) # [2, 3]


---

## Быстрый мини-анализ набора данных

Соберём всё вместе:

import statistics as stats

data = [12, 15, 17, 15, 19, 21, 15, 18]

summary = {
"mean": stats.mean(data),
"median": stats.median(data),
"mode": stats.mode(data),
"min": min(data),
"max": max(data)
}

print(summary)
# Пример вывода:
# {'mean': 16.5, 'median': 16.0, 'mode': 15, 'min': 12, 'max': 21}


Всего несколько строк — и вы уже видите «портрет» своих данных: где центр, где разброс и какое значение встречается чаще всего.

Модуль statistics — отличный первый шаг в сторону анализа данных, без pandas и сложной математики. Идеален для учебных задач, прототипов и маленьких утилит.
👍3