ru
Feedback
Python для начинающих

Python для начинающих

Открыть в Telegram

Python для начинающих

Больше
1 239
Подписчики
Нет данных24 часа
+17 дней
-130 день
Архив постов
Как использовать itertools: новый взгляд на циклы и генераторы Если обычные циклы for — это отвертка, то модуль itertools — целый чемодан инструментов. Он позволяет писать короче, читать легче и иногда вообще обходиться без явных циклов. --- ## Бесконечные последовательности без боли
from itertools import count, cycle, repeat

for i in count(10, 2):  # 10, 12, 14, ...
    if i > 20:
        break
    print(i)
count(start, step) создает бесконечный счетчик. Безопасность — на вас: обязательно ставьте break.
colors = ["red", "green", "blue"]
for c, n in zip(cycle(colors), range(5)):
    print(c)
cycle(iterable) зацикливает список. Удобно для повторяющихся паттернов.
for x in repeat("hello", 3):
    print(x)
repeat(obj, times) — ленивый клон объекта. --- ## Перебор сочетаний, перестановок и не только
from itertools import permutations, combinations, product

letters = ["a", "b", "c"]

print(list(permutations(letters, 2)))   # Порядок важен
print(list(combinations(letters, 2)))   # Порядок не важен
Такие функции идеально подходят для перебора вариантов в брутфорс-задачах, тестировании, комбинаторике. Декартово произведение:
sizes = ["S", "M"]
colors = ["black", "white"]

for combo in product(sizes, colors):
    print(combo)
Это мощнее вложенных циклов и проще читается. --- ## Умная фильтрация и группировка
from itertools import compress

data = [10, 20, 30, 40]
selectors = [True, False, True, False]

print(list(compress(data, selectors)))  # [10, 30]
compress фильтрует элементы по маске логических значений. Группировка подряд идущих одинаковых элементов:
from itertools import groupby

data = "aaabbccccd"

for char, group in groupby(data):
    print(char, len(list(group)))
# a 3, b 2, c 4, d 1
Полезно для простого сжатия или анализа последовательностей. --- ## Комбинирование итераторов как конструктор
from itertools import chain, islice

data1 = [1, 2]
data2 = [3, 4, 5]

merged = chain(data1, data2)          # ленивое "склеивание"
print(list(islice(merged, 0, 4)))     # берём только первые 4
chain объединяет несколько источников, а islice позволяет "отрезать" нужный кусок без создания лишних списков. --- itertools — про ленивость и композицию. Вместо того чтобы писать сложные циклы, вы собираете поведение из маленьких строительных блоков. Результат — короче код, меньше ошибок и приятное ощущение "Python-стиля".

Как использовать itertools для нового взгляда на циклы и генераторы
Как использовать itertools для нового взгляда на циклы и генераторы

Работа с emoji и цветными иконками в консоли Python Консоль не обязана быть скучной. Немного emoji и цвета — и ваш скрипт начинает «разговаривать» с пользователем гораздо живее. Разберём три простых приёма: Unicode-emoji, библиотеку emoji и цветной вывод через colorama. --- ## 1. Emoji по‑простому: через Unicode Многие emoji — это обычные Unicode-символы. Достаточно вставить их прямо в строку:
print("Task completed ✅")
print("Warning ⚠️")
print("Python is fun 🐍")
Если консоль и шрифт поддерживают Unicode, всё просто заработает. Иногда полезно использовать кодовую точку:
smile = "\U0001F600"  # 😀
print(f"Hello {smile}")
--- ## 2. Библиотека emoji Когда хочется писать :smile: вместо поиска нужного символа. Установка:
pip install emoji
Использование:
import emoji

text = emoji.emojize(
    "Server status: :green_circle: Running, :red_circle: Stopped",
    language="alias"
)
print(text)
Полезные фишки: - emoji.demojize("Hello 😀")"Hello :grinning_face:" - Можно хранить «коды» в файлах настроек и подставлять emoji при выводе. --- ## 3. Цветной текст с colorama colorama кроссплатформенно добавляет цвет в консоль (особенно удобно на Windows). Установка:
pip install colorama
Минимальный пример:
from colorama import init, Fore, Style

init(autoreset=True)

print(Fore.GREEN + "Success ✅")
print(Fore.YELLOW + "Loading... ⏳")
print(Fore.RED + "Error ❌")
print(Style.DIM + "This is a low-priority message")
Ключевые элементы: - Fore.RED, Fore.GREEN, Fore.YELLOW и др. — цвет текста. - Style.BRIGHT, Style.DIM, Style.NORMAL — «стиль» текста. - autoreset=True избавляет от необходимости вручную сбрасывать цвет. --- ## 4. Комбинируем: мини‑панель статуса
from colorama import init, Fore
import emoji
import time

init(autoreset=True)

def show_status(message, ok=True):
    icon = ":check_mark_button:" if ok else ":cross_mark:"
    icon = emoji.emojize(icon, language="alias")
    color = Fore.GREEN if ok else Fore.RED
    print(color + icon, message)

show_status("Connecting to database...")
time.sleep(1)
show_status("Connected", ok=True)
show_status("Failed to fetch data", ok=False)
Итог: пара библиотек + Unicode — и ваша консоль превращается из серого лога в удобную и наглядную панель. Это особенно выручает в CLI‑утилитах, мини‑играх и учебных проектах, где хочется мгновенно различать успех, ошибку и предупреждения.

Работа с emoji и вывод цветных иконок в консоль Python
Работа с emoji и вывод цветных иконок в консоль Python

Создание простых Webhook-обработчиков с Flask Иногда нужно, чтобы ваш скрипт реагировал на внешние события: оплата на сайте, новый комментарий в соцсети, пуш из GitHub и т.п. Сервисы решают это через webhooks — они отправляют HTTP-запросы (обычно POST) на ваш URL. Ваша задача — принять запрос и что-то сделать. Самый простой способ в Python — мини-фреймворк Flask. --- ### Минимальный Webhook на Flask Установим Flask:
pip install flask
Создадим app.py:
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route("/webhook", methods=["POST"])
def webhook_handler():
    data = request.get_json(silent=True) or {}
    event_type = data.get("event", "unknown")

    # Примитивная обработка события
    if event_type == "payment_succeeded":
        # здесь могла бы быть запись в базу или отправка email
        print("Payment succeeded:", data)
    else:
        print("Unknown event:", data)

    return jsonify({"status": "ok"}), 200

if __name__ == "__main__":
    app.run(port=5000, debug=True)
Что тут важно: - methods=["POST"] — принимаем только POST (классический формат webhook’ов). - request.get_json() — достаем JSON-тело запроса. - Возвращаем JSON-ответ и HTTP-код 200, чтобы внешний сервис понял, что все прошло успешно. --- ### Как протестировать без реального сервиса Можно «прикинуться» внешним сервисом с помощью curl:
curl -X POST http://127.0.0.1:5000/webhook \
     -H "Content-Type: application/json" \
     -d '{"event":"payment_succeeded","amount":1500}'
В консоли сервера вы увидите распечатанный JSON. --- ### Добавляем простую проверку подписи Реальные сервисы почти всегда подписывают запросы, чтобы никто не мог отправить фальшивый webhook. Простейший вариант — общий секрет и заголовок с HMAC:
import hmac
import hashlib
from flask import abort

SECRET_TOKEN = "super-secret-key"

def verify_signature(raw_body: bytes, received_signature: str) -> bool:
    mac = hmac.new(SECRET_TOKEN.encode(), msg=raw_body, digestmod=hashlib.sha256)
    expected_sig = mac.hexdigest()
    return hmac.compare_digest(expected_sig, received_signature or "")

@app.route("/secure-webhook", methods=["POST"])
def secure_webhook():
    raw_body = request.data
    signature = request.headers.get("X-Signature")

    if not verify_signature(raw_body, signature):
        abort(401, description="Invalid signature")

    payload = request.get_json(silent=True) or {}
    print("Secure event:", payload)
    return jsonify({"status": "accepted"}), 200
Ключевые моменты: - Используем request.data, а не уже разобранный JSON — подпись считается по «сырому» телу. - hmac.compare_digest защищает от атак по времени сравнения. - При неверной подписи сразу возвращаем 401. --- ### Зачем это все начинающему? Webhook-обработчик — это реальная задачка уровня «боевого» кода: - вы работаете с HTTP, JSON, заголовками и кодами ответа; - думаете о безопасности (подписи, проверка метода); - учитесь разделять «прием запроса» и «бизнес-логику». А Flask позволяет уложить все это в несколько десятков строк понятного кода — отличный старт для вхождения в мир веб-разработки на Python.

Создание простых Webhook-обработчиков с Flask
Создание простых Webhook-обработчиков с Flask

Как использовать set для удаления дубликатов из списка Одна из самых частых задач в Python — избавиться от дубликатов в списке. Можно писать циклы, проверять, есть ли элемент в новом списке… а можно использовать встроенный тип set и сделать всё в одну строку. ### Что такое set? set — это множество: неупорядоченная коллекция уникальных элементов. Ключевые свойства: - в set не бывает дубликатов; - элементы должны быть хешируемыми (числа, строки, кортежи и т.д.); - порядок не гарантируется. Создать множество из списка можно так:
numbers = [1, 2, 2, 3, 3, 3]
unique_numbers = set(numbers)
print(unique_numbers)  # {1, 2, 3}
Мы просто «заставили» Python выкинуть всё лишнее. ### Возврат к списку без дубликатов Часто нужен именно список (с индексами и возможностью изменять элементы). Тогда:
numbers = [1, 2, 2, 3, 3, 3]
unique_list = list(set(numbers))
print(unique_list)  # порядок не гарантируется
Важно: порядок элементов может измениться. Для чисел это обычно не критично, но для, скажем, событий во времени — уже проблема. ### Как сохранить порядок и убрать дубликаты? Комбинируем set и цикл:
items = ["a", "b", "a", "c", "b", "d"]
seen = set()
result = []

for item in items:
    if item not in seen:
        seen.add(item)
        result.append(item)

print(result)  # ['a', 'b', 'c', 'd']
Здесь: - seen хранит уже встреченные элементы; - result — итоговый список без повторов, в исходном порядке. ### Короткая версия через dict.fromkeys Если важен порядок, но не хочется писать цикл:
items = ["a", "b", "a", "c", "b", "d"]
result = list(dict.fromkeys(items))
print(result)  # ['a', 'b', 'c', 'd']
До Python 3.7 порядок ключей в dict официально не гарантировался, но в современных версиях этот трюк работает надёжно. ### Где это полезно? - очистка списков e-mail адресов от повторов; - фильтрация тегов; - удаление дубликатов из данных перед анализом. Главное: set — быстрый и простой способ получить уникальные значения. Используйте set, когда порядок не важен, и сочетайте его с дополнительной логикой, когда порядок нужно сохранить.

Как использовать set для удаления дубликатов из списка
Как использовать set для удаления дубликатов из списка

### Создание внутренней документации с использованием docstrings Одна из самых недооценённых суперспособностей Python — встроенная документация через docstrings. Это те самые строки в тройных кавычках сразу под объявлением функции, класса или модуля. Они не просто для красоты: по ним работают help(), IDE-подсказки и автогенерация документации. --- ## Зачем нужны docstrings Без них ваш код быстро превращается в загадку: - вы забываете, что делает функция; - непонятно, какие аргументы ожидать; - сложно понять, что именно возвращается. Docstring — это краткий контракт функции: что она делает, какие принимает параметры и что возвращает. --- ## Базовый пример docstring
def calculate_discount(price, discount):
    """
    Calculate final price after applying a percentage discount.

    Args:
        price (float): Original price.
        discount (float): Discount in percent, from 0 to 100.

    Returns:
        float: Price after discount.

    Raises:
        ValueError: If discount is not between 0 and 100.
    """
    if not 0 <= discount <= 100:
        raise ValueError("Discount must be between 0 and 100.")
    return price * (1 - discount / 100)
Теперь достаточно вызвать:
help(calculate_discount)
и вы получите аккуратную справку по функции прямо в консоли. --- ## Docstrings в модулях и классах Документировать стоит не только функции:
"""
tools.pricing module.

Contains utilities for working with prices and discounts.
"""

class PriceCalculator:
    """
    Helper class for price calculation logic.
    """

    def __init__(self, tax_rate):
        """
        Initialize calculator.

        Args:
            tax_rate (float): Tax in percent.
        """
        self.tax_rate = tax_rate

    def with_tax(self, price):
        """
        Add tax to the price.

        Args:
            price (float): Base price.

        Returns:
            float: Price including tax.
        """
        return price * (1 + self.tax_rate / 100)
Такие docstrings позволяют быстро понять архитектуру модуля: о чём он, какие есть классы, чем они занимаются. --- ## Какой стиль использовать Наиболее популярны два стиля: 1. Google-style (как в примерах выше: Args:, Returns:, Raises:) 2. NumPy-style (разделы Parameters, Returns с табличным форматированием) Главное — выбрать один стиль и придерживаться его в проекте. Это делает документацию предсказуемой и удобной. --- ## Мини‑лайфхаки - Первая строка docstring — краткое описание в одном предложении. - Дальше — подробности, пример использования, нюансы. - Не описывайте «что написано в коде», описывайте зачем это нужно и какие ожидания у функции. Хорошо написанные docstrings превращают ваш код в само-документируемую систему. А это уже уровень разработчика, с которым приятно работать не только компьютеру, но и людям.

Создание внутренней документации с использованием docstrings
Создание внутренней документации с использованием docstrings

Использование zip для параллельной обработки списков В Python есть маленькая, но очень мощная функция — zip. Она решает типичную задачу: «у меня есть несколько списков, нужно пройтись по ним параллельно». Без zip код часто превращается в кашу из индексов. ### Базовый пример: два списка одновременно Допустим, у нас есть список имён и список оценок:
names = ["Alice", "Bob", "Charlie"]
scores = [95, 82, 77]

for name, score in zip(names, scores):
    print(name, "->", score)
Цикл одновременно берет по одному элементу из каждого списка: сначала ("Alice", 95), потом ("Bob", 82) и так далее. Важно: zip останавливается, когда самый короткий список заканчивается. --- ### Создание словаря из двух списков Классическая задача для начинающих — склеить два списка в словарь: ключи и значения.
keys = ["host", "port", "debug"]
values = ["localhost", 8080, True]

config = dict(zip(keys, values))
print(config)
# {'host': 'localhost', 'port': 8080, 'debug': True}
Получается читабельно и без лишних циклов и индексов. --- ### Обработка более чем двух списков zip не ограничивается двумя последовательностями:
products = ["Book", "Pen", "Bag"]
prices = [10.5, 1.2, 25.0]
quantities = [2, 10, 1]

for product, price, qty in zip(products, prices, quantities):
    total = price * qty
    print(product, "total:", total)
Так удобно считать суммы, собирать отчеты, формировать строки для вывода. --- ### Распаковка с помощью zip(*) Трюк наоборот: «поворот» структуры. Допустим, у нас уже есть список пар:
pairs = [("x1", 10), ("x2", 20), ("x3", 30)]

labels, values = zip(*pairs)
print(labels)  # ('x1', 'x2', 'x3')
print(values)  # (10, 20, 30)
Оператор * распаковывает список, а zip пересобирает его по столбцам. Это удобно при работе с данными, которые приходят в виде списков кортежей. --- ### zip_longest из itertools Если списки разной длины и важно не терять элементы, берите:
from itertools import zip_longest

a = [1, 2, 3]
b = ["a", "b"]

for x, y in zip_longest(a, b, fillvalue=None):
    print(x, y)
Здесь недостающие элементы будут заменены fillvalue. --- zip — это способ сделать код более декларативным: вы говорите «обойди эти списки вместе», а не «пройди по индексам и вытащи элементы руками». Чем меньше индексов и вспомогательных счетчиков, тем проще читать и отлаживать программы.

Использование метода zip для параллельной обработки списков
Использование метода zip для параллельной обработки списков

Создаем простой email-отправщик с smtplib Рано или поздно почти каждому Python-разработчику нужно “научить” скрипт отправлять письма: отчеты, уведомления, результаты парсинга. Для этого в стандартной библиотеке уже есть всё необходимое — модуль smtplib. --- ## Минимальный отправщик письма Отправим простое письмо через SMTP-сервер (например, Gmail).
import smtplib
from email.mime.text import MIMEText

smtp_server = "smtp.gmail.com"
smtp_port = 587

sender_email = "you@example.com"
sender_password = "app_password"
receiver_email = "friend@example.com"

subject = "Test email from Python"
body = "Hello!\nThis is a test email sent from a Python script."

msg = MIMEText(body, "plain", "utf-8")
msg["Subject"] = subject
msg["From"] = sender_email
msg["To"] = receiver_email

with smtplib.SMTP(smtp_server, smtp_port) as server:
    server.starttls()                         # шифруем соединение
    server.login(sender_email, sender_password)
    server.send_message(msg)
Ключевые моменты: - smtplib.SMTP — подключение к серверу. - starttls() — перевод соединения в защищенный режим (обязательно для большинства провайдеров). - login() — авторизация. - send_message() — отправка готового объекта письма. Для Gmail и некоторых других сервисов часто нужен не “обычный” пароль, а пароль приложения (app password). --- ## Несколько получателей и HTML-письмо Сделаем отправщик чуть умнее: добавим список адресов и HTML-тело.
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import smtplib

smtp_server = "smtp.gmail.com"
smtp_port = 587

sender_email = "you@example.com"
sender_password = "app_password"
receivers = ["user1@example.com", "user2@example.com"]

msg = MIMEMultipart("alternative")
msg["Subject"] = "Daily report"
msg["From"] = sender_email
msg["To"] = ", ".join(receivers)

text_part = MIMEText("Plain text fallback", "plain", "utf-8")
html_part = MIMEText(
    """
    <h1>Daily report</h1>
    <p>Everything is <b>OK</b>.</p>
    """,
    "html",
    "utf-8"
)

msg.attach(text_part)
msg.attach(html_part)

with smtplib.SMTP(smtp_server, smtp_port) as server:
    server.starttls()
    server.login(sender_email, sender_password)
    server.sendmail(sender_email, receivers, msg.as_string())
Теперь письмо красиво отображается в почтовом клиенте, а если HTML отключен — будет использована текстовая версия. --- ## Быстрая обертка в функцию Чтобы не копировать один и тот же код в каждом проекте, удобно сделать маленькую утилиту:
def send_email(subject, body, to_emails):
    import smtplib
    from email.mime.text import MIMEText

    smtp_server = "smtp.gmail.com"
    smtp_port = 587
    sender_email = "you@example.com"
    sender_password = "app_password"

    msg = MIMEText(body, "plain", "utf-8")
    msg["Subject"] = subject
    msg["From"] = sender_email
    msg["To"] = ", ".join(to_emails)

    with smtplib.SMTP(smtp_server, smtp_port) as server:
        server.starttls()
        server.login(sender_email, sender_password)
        server.sendmail(sender_email, to_emails, msg.as_string())
Теперь любой скрипт может за пару строк отправить уведомление:
send_email("Job finished", "Your script has completed successfully.", ["admin@example.com"])
Так из сухого протокола SMTP получается удобный инструмент автоматизации: скрипт не просто “что-то делает”, а сам сообщает о результате.

Создание простого email-отправщика с smtplib
Создание простого email-отправщика с smtplib

Преобразование кодировок текста в Python с использованием codecs Когда начинаешь работать с текстом, кажется, что строки — это просто строки. А потом внезапно появляются кракозябры вместо букв, и становится ясно: кодировки — реальны, боль — тоже. Модуль codecs в Python помогает эту боль контролировать. ### Зачем нужен codecs, если есть open? Современный способ — использовать встроенный open(..., encoding="utf-8"). Но codecs полезен, когда нужно: - читать/писать файлы в нестандартных кодировках (cp1251, koi8-r и т.п.); - конвертировать текст из одной кодировки в другую; - тонко управлять обработкой ошибок. ### Базовый пример: чтение и запись с codecs.open
import codecs

# Читаем файл в кодировке cp1251 и сохраняем в utf-8
with codecs.open("input_cp1251.txt", "r", encoding="cp1251") as f_in:
    text = f_in.read()

with codecs.open("output_utf8.txt", "w", encoding="utf-8") as f_out:
    f_out.write(text)
Здесь Python сам декодирует байты из cp1251 в строку (str), а затем кодирует её в utf-8 при записи. ### Прямое преобразование байтов Иногда текст уже в памяти в виде байтов, и нужно просто перекодировать:
import codecs

data_cp1251 = b'\xcf\xf0\xe8\xe2\xe5\xf2'  # байты в cp1251

# Декодируем байты -> str, затем кодируем в другую кодировку
text = data_cp1251.decode("cp1251")
data_utf8 = text.encode("utf-8")
Тот же эффект можно получить с codecs.decode и codecs.encode:
import codecs

data_cp1251 = b'\xcf\xf0\xe8\xe2\xe5\xf2'
text = codecs.decode(data_cp1251, "cp1251")
data_utf8 = codecs.encode(text, "utf-8")
### Обработка ошибок: errors="ignore", replace, strict Если в потоке байтов встречаются “битые” символы, полезно управлять тем, как Python на это реагирует:
import codecs

with codecs.open("broken.txt", "r", encoding="utf-8", errors="replace") as f:
    text = f.read()
Популярные варианты: - strict — по умолчанию, выбросит ошибку UnicodeDecodeError; - ignore — пропустит проблемные символы; - replace — заменит их на ? или спецсимвол . ### Потоковое преобразование: codecs.StreamReaderWriter Если нужно конвертировать “на лету”, не загружая весь файл в память:
import codecs

with open("input_cp1251.txt", "rb") as f_in, \
     open("output_utf8.txt", "wb") as f_out:

    reader = codecs.getreader("cp1251")(f_in)
    writer = codecs.getwriter("utf-8")(f_out)

    for line in reader:
        writer.write(line)
Здесь reader читает байты и сразу выдаёт строки, а writer принимает строки и записывает их в нужной кодировке. --- codecs — это “швейцарский нож” для кодировок в Python. Даже если в повседневной работе вы используете только open(..., encoding="utf-8"), умение при необходимости достать из рукава codecs часто спасает проекты, столкнувшиеся с “наследственными” файлами и старыми системами.

Преобразование кодировок текста в Python с использованием codecs
Преобразование кодировок текста в Python с использованием codecs

Изучение math и cmath: когда числа становятся сложными Большинство задач в Python решаются на обычных (действительных) числах. Но как только появляются углы, корни из отрицательных чисел или работа с сигналами — без комплексных чисел не обойтись. За них в Python отвечают два модуля: math и cmath. --- ### math: строгий мир действительных чисел math работает только с int и float. Попробуйте передать комплексное число — получите ошибку. Основные возможности: - тригонометрия: sin, cos, tan, переводы радиан/градусов; - корни, логарифмы, экспонента: sqrt, log, exp; - константы: pi, e, tau.
import math

angle_deg = 60
angle_rad = math.radians(angle_deg)

h = 10
base = h * math.cos(angle_rad)
height = h * math.sin(angle_rad)

print(base, height)  # расчет проекции вектора на оси
math строг к вводимым значениям. Например, math.sqrt(-1) выдаст ValueError: для него отрицательный корень — недопустим. --- ### cmath: когда отрицательные корни — это нормально cmath — аналог math, но для комплексных чисел. Он спокойно принимает как float, так и complex, и возвращает именно комплексные числа.
import cmath

z = -1
root = cmath.sqrt(z)
print(root)          # (0+1j)
print(root.real)     # действительная часть
print(root.imag)     # мнимая часть
Ключевые функции и особенности: - те же sin, cos, exp, log, sqrt, но для комплексных; - полярная форма: phase(z), polar(z), rect(r, phi).
import cmath

z = 1 + 1j

r, phi = cmath.polar(z)   # модуль и аргумент
print(r, phi)

z2 = cmath.rect(r, phi)   # обратно в алгебраическую форму
print(z2)
--- ### Как понять, что тебе нужен cmath, а не math? - Нужен корень из «подозрительного» выражения (может стать отрицательным)? - Работаешь с сигналами, Фурье, электрическими цепями, квантовой механикой? - В формулах явно фигурирует i (или j)? Тогда используй complex и cmath:
import cmath

a, b, c = 1, 2, 5  # дискриминант отрицательный
d = b**2 - 4*a*c

x1 = (-b + cmath.sqrt(d)) / (2*a)
x2 = (-b - cmath.sqrt(d)) / (2*a)

print(x1, x2)
--- Итого: - math — быстрый и строгий мир действительных чисел. - cmath — тот же набор инструментов, но без страха перед мнимой единицей j. Понимание разницы между ними — первый шаг к задачам уровнем выше простых калькуляторных вычислений.

Изучение math и cmath: работа с действительными и комплексными числами
Изучение math и cmath: работа с действительными и комплексными числами

Создаем мини-базу данных на JSON: простой путь без SQL Иногда для небольших проектов полноценная база данных — это как использовать экскаватор, чтобы посадить цветок. Для заметок, простого TODO, небольшого чата или прототипа вполне хватит обычного файла JSON. Давай сделаем свою мини-БД шаг за шагом. --- ### Почему JSON? - Читается человеком (открыл файл — и сразу видно данные). - Встроенная поддержка в Python (json модуль). - Легко переносить между проектами и языками. --- ### Базовые операции «мини-БД» Нам нужны минимум 4 вещи: 1. Сохранить данные 2. Прочитать данные 3. Добавить запись 4. Найти запись по условию Создадим файл db.json и модуль mini_db.py.
# mini_db.py
import json
from pathlib import Path

DB_FILE = Path("db.json")


def load_data():
    if not DB_FILE.exists():
        return []
    with DB_FILE.open("r", encoding="utf-8") as f:
        return json.load(f)


def save_data(data):
    with DB_FILE.open("w", encoding="utf-8") as f:
        json.dump(data, f, indent=2, ensure_ascii=False)
Теперь напишем функции для работы с записями. Пусть это будет мини-БД пользователей:
def add_user(name, age):
    data = load_data()
    new_id = (max((item["id"] for item in data), default=0) + 1)
    user = {"id": new_id, "name": name, "age": age}
    data.append(user)
    save_data(data)
    return user


def find_users_by_name(name):
    data = load_data()
    return [item for item in data if item["name"] == name]
Использование:
if __name__ == "__main__":
    add_user("Alice", 25)
    add_user("Bob", 30)
    print(find_users_by_name("Alice"))
--- ### Добавляем «фишки»: фильтрация и обновление Мини-БД станет полезнее, если можно будет: - фильтровать по произвольному условию - обновлять записи
def filter_users(condition):
    data = load_data()
    return [item for item in data if condition(item)]


def update_user(user_id, **fields):
    data = load_data()
    updated = None
    for item in data:
        if item["id"] == user_id:
            item.update(fields)
            updated = item
            break
    if updated:
        save_data(data)
    return updated
Пример:
# Все пользователи старше 20
adults = filter_users(lambda u: u["age"] > 20)

# Обновляем возраст
update_user(1, age=26)
--- ### Когда такой подход годится Подходит, если: - проект маленький; - данных мало (до нескольких тысяч записей); - не нужны сложные запросы и транзакции. Если же требуется многопользовательский доступ, высокая нагрузка, сложная аналитика — тогда пора смотреть в сторону SQLite, PostgreSQL и других БД. Но для начала изучения Python и быстрых прототипов JSON-«база» — отличный и наглядный инструмент, который ты полностью контролируешь.

Создание своей мини-базы данных с использованием JSON
Создание своей мини-базы данных с использованием JSON