Zen of Python
20.1K subscribers
1.29K photos
178 videos
36 files
3.3K links
Полный Дзен Пайтона в одном канале

Разместить рекламу: @tproger_sales_bot

Правила общения: https://tprg.ru/rules

Другие каналы: @tproger_channels

Сайт: https://tprg.ru/site

Регистрация в перечне РКН: https://tprg.ru/xZOL
Download Telegram
​​Как сеньоры документируют проекты: протокол архитектурных решений

В статье рассказывается, как сеньоры применяют ADR (Architectural Decision Record — протокол архитектурных решений), чтобы документировать важные архитектурные изменения, их причины и последствия. ADR помогает сохранять логику принятия решений, избегать повторений ошибок и облегчает командную работу, особенно для новых участников. Автор сравнивает такой протокол с «личным дневником, но для всей команды», подчеркивая его пользу в будущем: спустя время возвращаться к архитектурным мотивам становится гораздо проще.

#основы
@zen_of_python
💅 — Если применяешь такое
41👍1💅1
Вопрос подписчика

Задает @StSav012:

«Предлагаю задачку на алгоритм.
Для данных n ∈ ℕ и чётного N ≥ n > 1, N ∈ ℕ, найти чётное ñ, ближайшее к n, являющееся делителем N. Если таких чисел несколько, выбрать наибольшее.Конечно, хочется скорость O(log(n)).


def find_closest_even_divisor(n: int, max_n: int) -> int:
"""
For given n ∈ ℕ and an even N ≥ n, N ∈ ℕ,
find an even ñ closest to n so that ñ is a divisor of N.

If there are several such numbers, pick the largest one.
"""

if max_n <= 0:
raise ValueError(f"There are no positive divisors for {max_n}")
if max_n & 1:
raise ValueError(f"There are no even divisors for {max_n}, which is odd")

if n > 0.75 * max_n:
return max_n

if max_n % n == 0 and n & 1 == 0:
return n

divisors: list[int] = []
dd: int = 1
while max_n > 1 and max_n & 1 == 0:
max_n >>= 1
dd <<= 1
divisors.append(dd)

d: int = 3
dc: list[int]
while max_n > 1:
dc = []
dd = 1
while max_n % d == 0:
max_n //= d
dd *= d
dc.append(dd)
else:
if dc:
divisors += [divisor * dd for divisor in divisors for dd in dc]
if d < isqrt(max_n) and d < 2 * n:
d += 2
else:
break

return min(divisors, key=lambda _d: (abs(n - _d), -_d))

Что ещё можно ускорить?»

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

#обсуждение
@zen_of_python
1
Forwarded from Типичный программист
This media is not supported in your browser
VIEW IN TELEGRAM
CodeViz: бесплатное дополнение для VS Code, превращающее код в интерактивную карту 😬

Плагин строит визуальную структурированную карту вашего кода прямо в IDE. Можно наглядно увидеть архитектуру проекта, связи между файлами и понять его суть.

Поддерживается масса яп, всё работает быстро и абсолютно бесплатно. Сохраняйте.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤‍🔥103🔥1
Цепочка обязанностей

Цепочка обязанностей (Chain of Responsibility, CoR) — поведенческий паттерн, который пропускает запрос через последовательность обработчиков, пока один из них не возьмётся за дело (или пока цепочка не закончится). Этот подход «развязывает» отправителя и получателей запроса: отправителю не нужно знать, кто именно обработает задачу, а обработчики остаются взаимозаменяемыми и настраиваемыми в рантайме.

Используйте CoR, если:

🔘 обработка запроса может зависеть от набора условий/правил, которые меняются со временем;
🔘 нужно включать / выключать шаги обработки без переписывания вызвавшего кода;
🔘 часть запросов может обрабатываться на ранних шагах, а остальные — «прокатываться» дальше;
🔘 вы строите конвейер: фильтры, middleware, валидаторы, пост-обработчики.


Минимальный состав паттерна

🔘 Handler (интерфейс / абстракция): объявляет метод handle(request) и хранит ссылку на «следующего»;
🔘 ConcreteHandler: решает, обрабатывать ли запрос, либо передаёт дальше;
🔘 Client: строит цепочку и отправляет запрос первому звену.


Пример


from __future__ import annotations
from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import Optional, Any, Callable


class Handler(ABC):
def __init__(self, nxt: Optional["Handler"] = None):
self._next = nxt

def set_next(self, nxt: "Handler") -> "Handler":
self._next = nxt
return nxt # позволяет строить цепочку «в линию»

def handle(self, request: Any) -> Any:
# Базовая реализация: попытаться обработать здесь,
# иначе передать дальше.
result = self._handle_here(request)
if result is not None:
return result
if self._next:
return self._next.handle(request)
return None # никто не справился

@abstractmethod
def _handle_here(self, request: Any) -> Optional[Any]:
...


@dataclass
class HttpRequest:
path: str
headers: dict
user_id: Optional[int] = None
payload: Optional[dict] = None


class AuthHandler(Handler):
def _handle_here(self, req: HttpRequest) -> Optional[Any]:
token = req.headers.get("Authorization")
if not token:
# Нет токена — «решение на месте»: отклоняем и НЕ передаём дальше
return {"status": 401, "message": "Unauthorized"}
# валидируем (упростим) и ставим идентификатор
req.user_id = 42
return None # пропускаем дальше


class RateLimitHandler(Handler):
def __init__(self, check: Callable[[HttpRequest], bool], nxt: Optional[Handler] = None):
super().__init__(nxt)
self.check = check

def _handle_here(self, req: HttpRequest) -> Optional[Any]:
if not self.check(req):
return {"status": 429, "message": "Too Many Requests"}
return None


class RouterHandler(Handler):
def _handle_here(self, req: HttpRequest) -> Optional[Any]:
if req.path == "/me" and req.user_id:
return {"status": 200, "data": {"id": req.user_id}}
if req.path == "/ping":
return {"status": 200, "data": "pong"}
# Не мой маршрут — пропускаю дальше (если есть)
return None


class NotFoundHandler(Handler):
def _handle_here(self, req: HttpRequest) -> Optional[Any]:
# Терминальный обработчик: если дошли сюда — 404
return {"status": 404, "message": f"Route {req.path} not found"}


# Сборка цепочки
def build_pipeline() -> Handler:
auth = AuthHandler()
rate = RateLimitHandler(check=lambda r: True)
router = RouterHandler()
notfound = NotFoundHandler()

auth.set_next(rate).set_next(router).set_next(notfound)
return auth


if __name__ == "__main__":
pipeline = build_pipeline()
print(pipeline.handle(HttpRequest(path="/ping", headers={"Authorization": "Bearer x"})))
print(pipeline.handle(HttpRequest(path="/me", headers={"Authorization": "ok"})))
print(pipeline.handle(HttpRequest(path="/unknown", headers={"Authorization": "ok"})))
print(pipeline.handle(HttpRequest(path="/ping", headers={})))
Please open Telegram to view this post
VIEW IN TELEGRAM
6
Этот код демонстрирует:
🔘 короткое замыкание (401 и 429 останавливают конвейер);
🔘 прохождение запроса дальше при None;
🔘 терминальный обработчик 404.


Политики прохождения запроса

🔘 Short-circuit (рекомендуется по умолчанию): первый, кто вернул результат, «закрывает» цепочку;
🔘 Fall-through: все обработчики обязаны отработать (например, аудит/метрики/логирование), результат — агрегация;
🔘 Микс: часть «жёстких» (аутентификация, лимиты) — short-circuit; «мягкие» (логирование) — всегда проходят.

#основы
@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
​​Вопрос подписчика

Задает @mozmoroz:

«Какие платные курсы с куратором можете посоветовать по питону для получения базы знаний с пониманием что такое питон и цикл if? Возраст 15 лет»

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

#обсуждение
@zen_of_python
3
​​Hypothesis подумает о пограничных случаях за вас

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

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

#инструмент
@zen_of_python
3🌭1
This media is not supported in your browser
VIEW IN TELEGRAM
alive-progress | Шкала прогресса в CLI

Библиотека, предназначенная для создания динамичных индикаторов прогресса в CLI. Среди фичей:
— плавная анимация спиннера;
— точный расчет оставшегося времени с использованием алгоритма экспоненциального сглаживания;
— хуки для логирования.

#инструмент #dataviz
@zen_of_python
1👏1😱1
Вопросы подписчиков

Zen of Python поддерживает новоприбывших (и не только) в особой рубрике. Как это работает:

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

#обсуждение
@zen_of_python
Новый синтаксис Python от Grok
#кек
@zen_of_python
16😁5
Forwarded from IT Юмор
Надо ещё добавить пару строк с комментами для количества

@ithumor
😁12🔥21
This media is not supported in your browser
VIEW IN TELEGRAM
Когда вынужден работать с несколькими версиями Python в своих проектах
#кек
@zen_of_python
😁5🔥1💯1
Forwarded from Типичный программист
Лимитка для комьюнити выходит в прод! Успей залететь в розыгрыш

Уже скоро День программиста, и к этому моменту наш безалкогольный IPA будет разлит!

Вы выбрали название и концепт упаковки, а наши коллеги по коллабу из Paradox уже отдали этикетки в печать.

И пока мы с вами ожидаем релиза, запускаем специальный розыгрыш.

Победитель получит коробку «ТОКСИЧНЫЙ ПРОГРАММИСТ» с шестью банками. Подробнее с правилами вы можете ознакомиться здесь.

Для участия достаточно:
— быть подписанным на @tproger и @paradox_beer;
— оставить реакцию и любой комментарий под этим постом;
— нажать кнопку «Участвую».

Итоги подведём 15 сентября. Победителя выберем с помощью бота. Всем удачи!

Участников: 154
Призовых мест: 1
Дата розыгрыша: 18:00, 15.09.2025 MSK (3 дня)
1❤‍🔥1
Травма поколений в исполнении Python-комьюнити

#кек
@zen_of_python
😁3
Что такое линтер и что он делает

Линтер - это инструмент статического анализа кода, который проверяет ваш код на темы:
🔘 Синтаксис - правильно ли расставлены скобки, двоеточия;
🔘 Импорты - все ли импорты используются;
🔘 Переменные - все ли переменные определены;
🔘 Стиль - соответствие PEP 8;
🔘 Типы - если используется типизация.


Зачем запускать после изменений

⚡️ Обнаружение новых ошибок

# После добавления нового кода
def new_feature():
unused_var = "not used" # Линтер найдет неиспользуемую переменную
return "feature"


⚡️ Проверка совместимости

# После изменения импортов
from new_module import new_function
# Линтер проверит, существует ли new_function


⚡️ Соблюдение стандартов

# После рефакторинга
class MyClass:
def __init__(self):
self.very_long_attribute_name_that_should_be_shorter = None
# Линтер предложит сократить имя


⚡️ Проблемы безопасности

import subprocess
user_input = input("Enter command: ")
subprocess.run(user_input, shell=True) # Линтер предупредит о SQL injection


⚡️ Неэффективный код

# Неэффективно
my_list = []
for i in range(1000):
my_list.append(i)

# Линтер может предложить list comprehension
my_list = [i for i in range(1000)]


Настройка линтера
Обычно линтер настраивается через файлы конфигурации:


# pyproject.toml
[tool.ruff]
line-length = 88 # Максимальная длина строки
target-version = "py38" # Версия Python


Мы можем тонко настраивать, каким именно правилам следовать:

[tool.ruff.lint]
select = ["E", "F", "W", "C90", "I", "N", "UP", "YTT", "S", "BLE", "FBT", "B", "A", "COM", "C4", "DTZ", "T10", "EM", "EXE", "FA", "ISC", "ICN", "G", "INP", "PIE", "T20", "PYI", "PT", "Q", "RSE", "RET", "SLF", "SLOT", "SIM", "TID", "TCH", "INT", "ARG", "PTH", "TD", "FIX", "ERA", "PD", "PGH", "PL", "TRY", "FLY", "NPY", "AIR", "PERF", "FURB", "LOG", "RUF"]
ignore = ["E501", "S101", "PLR0913", "PLR0912", "PLR0915"]



Классические линтеры
🔘Pylint
🔘ruff
🔘Flake8
🔘mypy
🔘black

Пользователи Cursor, возможно, обратили внимание на завтозапуск линтера после практически каждого внесенного изменения. Эта IDE не отдает предпочтения какому-то конкретному инструменту, но запускает несколько из них.

Список правил ruff с детализацией в доках
#основы
@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
21👍1
Алгоритмы и структуры данных на Python

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

#обучение
@zen_of_python
21
​​python-dateutil | datetime, который смог

Ультрапопулярное (если верить рейтингу PyPi) расширение стандартного модуля datetime, поддерживает:

— Вычисление «следующего X»: удобно находим даты следующего понедельника или последней недели месяца;
— Относительные дельты: вычисляем разницу между двумя датами не только в секундах, но и в понятных календарных единицах (например, «2 месяца и 5 дней»);
— Рекуррентные даты (повторяющиеся события)
Поддерживается генерация серий дат по очень гибким правилам, расширяющим стандарт iCalendar (например: «каждый второй вторник месяца до конца года») и многое другое.

Еще бы русский язык поддерживала, цены бы не было!

#инструмент
@zen_of_python
​​YTSage | Скачиватель с YouTube

Инструмент с несложным GUI на PySide6 c yt-dlp под капотом. Позволяет выбрать HD-качество, извлечь субтитры. Поддерживает скачивание плейлистов с возможностью выбрать конкретные видео перед загрузкой.

#инструмент
@zen_of_python
Forwarded from Типичный программист
Кратко о современном деплое: контейнеризация, оркестрация и непрерывная доставка для вашего приложения

Развёртывание: это процесс, при котором ваше приложение становится доступно для пользователей. Современный деплой использует инструменты и пайплайны для обеспечения стабильности, скорости и надежности. Ниже попытались разложить всё по полочкам 👇

Docker (Контейнеризация)
🔘 Представьте Docker как транспортный контейнер для софта.
🔘 Он упаковывает код, библиотеки и зависимости так, чтобы приложение одинаково работало в любой среде.
🔘 Плюсы: портативность, изоляция и одинаковое поведение в dev-, staging- и production-средах.


Kubernetes (Оркестрация)
🔘 Когда контейнеров становится много, нужен управляющий.
🔘 Kubernetes — это как портовая служба, которая управляет контейнерами: масштабирует, перезапускает, балансирует нагрузку.
🔘 Обеспечивает балансировку нагрузки, масштабирование, поэтапные обновления и самовосстановление контейнерных приложений.

CI/CD (Непрерывная интеграция и доставка)
🔘 CI — это как проверка каждого продукта перед отправкой с завода: тесты запускаются автоматически при каждом пуше кода.
🔘 CD — это система доставки: одобренные изменения автоматически едут в production.
🔘 Плюсы: более быстрые релизы, меньше багов, проще командная работа.

Аналогия

🔘 Docker — Запечатанная коробка с вашим товаром.
🔘 Kubernetes — Логистическая компания, которая организует и доставляет все коробки по назначению.
🔘 CI/CD — Конвейер, на котором коробки непрерывно отправляются дальше без задержек.
Please open Telegram to view this post
VIEW IN TELEGRAM
🐳3👍1🗿1
Пост для питонисток: история PyLadies

Но история сообщества Python — это не только код. Это ещё и путь к тому, чтобы люди разного пола и разного опыта могли почувствовать себя в нём своими. Одним из главных шагов в этом направлении стало появление PyLadies.

От футболки с надписью «Python is for girls» к первому шагу

На заре популярности Python о гендерном балансе в сообществе почти не задумывались. Даже сама Python Software Foundation (PSF), по словам одного из участников документального фильма, состояла «исключительно из белых мужчин».

Даже когда Гвидо ван Россум на одной из PyCon публично заявил, что в PSF нужны женщины, ситуация почти не сдвинулась. В кулуарах и списках рассылки обсуждали код, но не то, как привлечь к этому коду новые голоса.

Прошло время, и выяснилось: простого заявления мало. Сообщество не менялось. Новые женщины-разработчицы по-прежнему чувствовали себя изолированными, а в «ядре» Python не было ни одной из них.

Только когда сам Гвидо решился на личное участие, ситуация начала меняться. Он взял на себя роль ментора для разработчицы Мариатты Виджайа, которая сначала сомневалась, «достойна ли» просить о поддержке создателя языка. Менторство Гвидо помогло ей преодолеть барьер и в итоге стать одной из первых женщин — Python Core Developers.

Сегодня именно две женщины, включая Мариатту, входят в PSF. Порой первым действовать должен начать глава.

PyLadies сегодня

Для крупных городов и даже целых стран начали создаваться локальные отделения: Pyadies Moscow, PyLadies Kazan, PyLadies Saint Petersburg. Только в этих сообществах, по мнению админа, сейчас как-то слишком тихо.

PyLadies не только увеличили долю женщин-спикеров на PyCon (с 1% в 2011 году до 40% в 2016-м), но и изменили саму культуру Python.

#факт
@zen_of_python
5🙉2😁1💅1