
- Главная
- Каталог
- Интернет технологии
- Библиотека Python разработчика
Статистика канала
pip install rich
2️⃣ Typer – современный способ писать CLI-приложения. Работает на основе аннотаций типов и делает разработку CLI удобнее.
📌 pip install typer
3️⃣ Pendulum – альтернатива datetime, но с удобным API и встроенной поддержкой часовых поясов.
📌 pip install pendulum
4️⃣ HTTPX – асинхронный клиент для работы с HTTP-запросами. Поддерживает async/await, в отличие от requests.
📌 pip install httpx
5️⃣ Pydantic – мощный инструмент для валидации данных и работы с моделями. Особенно полезен в FastAPI.
📌 pip install pydantic
6️⃣ Poetry – современный менеджер зависимостей. Упрощает работу с виртуальными окружениями и пакетами.
📌 pip install poetry
7️⃣ Loguru – удобная альтернатива стандартному logging. Позволяет логировать без лишнего кода.
📌 pip install loguru
8️⃣ FastAPI – один из самых быстрых Python-фреймворков для создания API. Использует аннотации типов и async/await.
📌 pip install fastapi
9️⃣ Tqdm – библиотека для удобных progress-bar'ов в терминале. Незаменима при обработке больших данных.
📌 pip install tqdm
🔟 Black – автоматический форматтер кода, который придерживается строгого стиля. Просто устанавливаешь – и больше не думаешь о стиле кода.
📌 pip install black
📲 Мы в MAX
👉@BookPythonmultiprocessing.Pool - это то, что вам нужно. Он создает несколько процессов и автоматически распределяет между ними задачи. Просто создайте пул с Pool(number_of_processes) и выполните p.map с списком входных данных.
import math
from multiprocessing import Pool
inputs = [i ** 2 for i in range(100, 130)]
def f(x):
return len(str(math.factorial(x)))
# Однопоточное выполнение
%timeit [f(x) for x in inputs]
# 1.44 s ± 19.2 ms per loop (...)
# Параллельное выполнение с 4 процессами
p = Pool(4)
%timeit p.map(f, inputs)
# 451 ms ± 34 ms per loop (...)
{}
Также можно не указывать параметр number_of_processes, по умолчанию он равен количеству ядер CPU в системе.
📲 Мы в MAX
👉@BookPythonabc.ABC в Python мы привыкли к Nominal Subtyping (Именная подтипизация). Чтобы объект считался Bird, он должен явно наследоваться от Bird.
Это создает жесткую связность (coupling): ваша реализация должна знать об интерфейсе и импортировать его.
С приходом typing.Protocol (Python 3.8+) мы получили Structural Subtyping (Структурная подтипизация).
В чем суть?
Если класс имеет метод quack(), то это Утка. Неважно, от чего он наследуется. Это и есть та самая «утиная типизация», но теперь поддерживаемая статическим анализатором (mypy, pyright, IDE).
Сравним код:
❌ Старый путь (ABC):
from abc import ABC, abstractmethod
# 1. Жестко определяем интерфейс
class SenderABC(ABC):
@abstractmethod
def send(self, msg: str) -> None: pass
# 2. Обязаны наследоваться!
class EmailService(SenderABC):
def send(self, msg: str) -> None:
print(f"Email: {msg}")
def alert(sender: SenderABC):
sender.send("Alert!")
{}
✅ Новый путь (Protocol):
from typing import Protocol
# 1. Описываем, "что мы ждем от объекта"
class SenderProto(Protocol):
def send(self, msg: str) -> None: ...
# 2. Реализация НИЧЕГО не знает про Protocol
# Никаких импортов и наследования!
class SmsService:
def send(self, msg: str) -> None:
print(f"SMS: {msg}")
# Mypy счастлив: SmsService имеет нужную структуру (метод send)
def alert(sender: SenderProto):
sender.send("Alert!")
alert(SmsService())
{}
Киллер-фича: Retroactive Abstraction (Ретроактивная абстракция)
Представьте, что вы используете стороннюю библиотеку (например, boto3 или клиент Redis). Вы не можете заставить их классы наследоваться от ваших ABC.
С помощью Protocol вы можете создать интерфейс для уже существующего чужого кода, не меняя его, и типизировать свои функции.
Нюансы для Middle+:
1. Runtime: По умолчанию isinstance(obj, MyProtocol) выбросит ошибку. Протоколы - это compile-time фича. Если нужна проверка в рантайме, декорируйте протокол @runtime_checkable.
2. Свойства: В протоколе можно описывать не только методы, но и поля через @property или просто аннотации типов.
Используйте Протоколы, чтобы развязать зависимости между модулями. Это основа принципа Dependency Inversion в Python.
#python #typing #mypy #architecture #clean_code
📲 Мы в MAX
👉@BookPythonХорошее API — это не только код, но и понятная документация. Без неё REST-сервис быстро превращается в чёрный ящик для команды и клиентов.Что будет на вебинаре:
@extend_schema и типизации.
yield и оптимизация скоупов
Если вы все еще пишете def teardown_method(self): в классах тестов, вы не используете мощь Pytest на 100%.
Фикстуры (fixtures) - это не просто способ передать данные. Это полноценный механизм управления жизненным циклом зависимостей (DI).
1. yield вместо return: Встроенный Teardown
В Pytest фикстура может "замереть", отдать управление тесту, а потом продолжить выполнение. Это реализуется через генератор yield.
Код до yield - это setUp.
Код после yield - это tearDown.
Пример (временная база данных):
import pytest
from sqlalchemy import create_engine
@pytest.fixture
def db_engine():
# Setup: Поднимаем соединение
engine = create_engine("sqlite:///:memory:")
# Передаем объект в тест
yield engine
# Teardown: Этот код выполнится ПОСЛЕ завершения теста
# (даже если тест упал с ошибкой!)
engine.dispose()
{}
Это гарантирует, что ресурсы будут освобождены, и вам не нужны try/finally блоки внутри самих тестов.
2. Scopes: Не создавайте мир заново
По умолчанию фикстура имеет scope='function'. Она создается и умирает для каждого теста. Это безопасно, но медленно, если мы говорим о поднятии Docker-контейнера или коннекта к БД.
Используйте scope='session' для тяжелых ресурсов, которые можно переиспользовать.
Паттерн "Изоляция при общем ресурсе":
Частая задача Middle+: иметь одну БД на весь прогон тестов (быстро), но чистые таблицы для каждого теста (изолированно).
Решение: комбинируем скоупы.
# Живет весь прогон тестов (создается 1 раз)
@pytest.fixture(scope="session")
def db_engine():
engine = create_engine(...)
yield engine
engine.dispose()
# Живет 1 тест (создается N раз)
@pytest.fixture(scope="function")
def db_session(db_engine):
# Берем engine из сессионной фикстуры
connection = db_engine.connect()
transaction = connection.begin() # Начали транзакцию
session = Session(bind=connection)
yield session
session.close()
# ROLLBACK транзакции после теста вернет базу в исходное состояние!
transaction.rollback()
connection.close()
{}
Итог:
yield для очистки ресурсов.
scope='session'.
scope='function', наследуясь от тяжелых.
#pytest #testing #qa #bestpractices #python
map, filter, reduce ⚡
Привет, друзья! Сегодня расскажу о том, как можно ускорить выполнение кода, заменяя обычные циклы на встроенные функции map(), filter() и reduce(). Эти инструменты позволяют писать более компактный, читаемый и быстрый код.
✅ map()
Функция map() применяется к каждому элементу последовательности и возвращает новый итератор.
❌ Обычный способ:
numbers = [1, 2, 3, 4, 5]
squared = []
for num in numbers:
squared.append(num ** 2)
{}
✅ Быстрее с map():
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x ** 2, numbers))
{}
За счёт того, что map() использует C-оптимизированную логику, код выполняется быстрее.
✅ filter()
Фильтрует элементы последовательности по заданному условию.
❌ Медленный вариант:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens = []
for num in numbers:
if num % 2 == 0:
evens.append(num)
{}
✅ Быстрее с filter():
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens = list(filter(lambda x: x % 2 == 0, numbers))
{}
Такой код читается легче и работает быстрее.
✅ reduce()
Позволяет выполнять кумулятивные операции (например, суммирование, умножение).
❌ Классический способ:
numbers = [1, 2, 3, 4, 5]
product = 1
for num in numbers:
product *= num
{}
✅ Быстрее с reduce():
from functools import reduce
numbers = [1, 2, 3, 4, 5]
product = reduce(lambda x, y: x * y, numbers)
{}
Этот метод полезен, если нужно свести список к одному значению.
💡 Важно: reduce() чаще заменяют sum() или math.prod(), но для сложных операций он остаётся полезным.
Такие функции помогают писать код, который не только быстрее работает, но и легче читается.
# Хотим создать 3 функции, которые возвращают 0, 1 и 2 соответственно
funcs = []
for i in range(3):
funcs.append(lambda: i)
# Проверяем
results = [f() for f in funcs]
print(results)
# Ожидание: [0, 1, 2]
# Реальность: [2, 2, 2]
{}
Почему так происходит?
Это называется Late Binding (позднее связывание).
В Python замыкания (closures) захватывают переменные по ссылке, а не по значению.
Когда вы объявляете lambda: i, Python не сохраняет текущее число 0, 1 или 2. Он сохраняет инструкцию: «когда меня вызовут, пойди в локальную область видимости, найди переменную с именем i и возьми ее значение».
К моменту, когда вы начинаете вызывать функции из списка results, цикл for уже завершился. Переменная i в этой области видимости навсегда осталась равной 2. Все три лямбды смотрят на одну и ту же переменную i.
Как лечить?
Есть два каноничных способа заставить Python запомнить значение «здесь и сейчас».
1. Аргумент по умолчанию (Hack way)
Значения аргументов по умолчанию вычисляются в момент определения функции.
funcs = []
for i in range(3):
# i=i создает локальную переменную i внутри функции
# и присваивает ей текущее значение i из цикла
funcs.append(lambda i=i: i)
{}
Это работает быстро, но выглядит немного грязно и может сбить с толку линтеры или коллег.
2. functools.partial (Enterprise way)
Более чистый и явный способ. partial создает новый callable-объект, «замораживая» переданные аргументы.
from functools import partial
funcs = []
for i in range(3):
# Здесь значение i фиксируется жестко
funcs.append(partial(lambda x: x, i))
{}
Где это стреляет в реальной жизни?
- Генерация command для кнопок в Tkinter/PyQt.
- Динамическое создание task в asyncio циклах.
- Патчинг тестов в циклах.
Не дайте переменным пережить свое время.
#python #internals #functionalprogramming #gotchas
Отзывы канала
всего 6 отзывов
- Добавлен: Сначала новые
- Добавлен: Сначала старые
- Оценка: По убыванию
- Оценка: По возрастанию
Каталог Телеграм-каналов для нативных размещений
Библиотека Python разработчика — это Telegam канал в категории «Интернет технологии», который предлагает эффективные форматы для размещения рекламных постов в Телеграмме. Количество подписчиков канала в 18.8K и качественный контент помогают брендам привлекать внимание аудитории и увеличивать охват. Рейтинг канала составляет 5.3, количество отзывов – 6, со средней оценкой 5.0.
Вы можете запустить рекламную кампанию через сервис Telega.in, выбрав удобный формат размещения. Платформа обеспечивает прозрачные условия сотрудничества и предоставляет детальную аналитику. Стоимость размещения составляет 8181.81 ₽, а за 30 выполненных заявок канал зарекомендовал себя как надежный партнер для рекламы в TG. Размещайте интеграции уже сегодня и привлекайте новых клиентов вместе с Telega.in!
Вы снова сможете добавить каналы в корзину из каталога
Комментарий