Б

Библиотека Python разработчика | Книги по питону

@bookpython

Погружение в CPython и архитектуру. Разбираем неочевидное поведение (GIL, Memory), Best Practices (SOLID, DDD) и тонкости Django/FastAPI. Решаем задачи с подвохом и оптимизируем алгоритмы. 🐍По всем вопросам @evgenycarterРКН clck.ru/3Ko7Hq

18 626 подписчиков
Несколько раз в неделюКачество: 82%🇷🇺 RUПоследний пост: 20.02.2026
Открыть в TelegramПоделиться в TG

Последние посты

Б
Библиотека Python разработчика | Книги по питону@bookpython

Стандартный модуль json имеет интерфейс командной строки, который может быть полезен для форматирования JSON исключительно средствами Python. Модуль называется json.tool и вызывается следующим образом:$ echo '{"a": [], "b": "c"}' | python -m json.tool{ "a": [], "b": "c"}📲 Мы в MAX👉@BookPython

4 мар. 2026 г.1 310В Telegram
Б
Библиотека Python разработчика | Книги по питону@bookpython

default_factory в dataclass: мощнее, чем кажетсяМногие используют dataclass как удобный способ задать структуру с полями. Но редко кто по-настоящему раскрывает силу default_factory. А зря — он спасает от багов и даёт гибкость.Когда нужно задать значение по умолчанию для поля в dataclass, логично тянуться к default=. Но если это изменяемый тип (например, список или словарь) — вас поджидает ловушка.from dataclasses import dataclass, field@dataclassclass User: name: str tags: list[str] = [] # ⚠️ опасно!Все экземпляры User будут делить один и тот же список. То есть:a = User("Alice")b = User("Bob")a.tags.append("admin")print(b.tags) # ['admin'] 😱Вместо этого используйте default_factory:@dataclassclass User: name: str tags: list[str] = field(default_factory=list)Теперь у каждого User будет свой список:a = User("Alice")b = User("Bob")a.tags.append("admin")print(b.tags) # []Но default_factory не только про списки. Это отличный способ задать любое значение "по умолчанию", включая кастомную логику:import uuid@dataclassclass Session: id: str = field(default_factory=lambda: str(uuid.uuid4()))Или, например, значения из окружения:import os@dataclassclass Config: debug: bool = field(default_factory=lambda: os.getenv("DEBUG") == "1")Кстати, это ещё и отличное место для внедрения DI:@dataclassclass Service: client: "Client" = field(default_factory=create_default_client)default_factory — это маленький хак, который позволяет сделать код чище и безопаснее, особенно когда работаешь с изменяемыми структурами или сложной инициализацией.📲 Мы в MAX👉@BookPython

3 мар. 2026 г.1 330В Telegram
Б
Библиотека Python разработчика | Книги по питону@bookpython

yield from — элегантная передача управленияЕсли вы пишете генераторы, которые вызывают другие генераторы — забудьте про for x in sub(): yield x. Есть способ проще и мощнее.Оператор yield from позволяет передавать элементы из подгенератора напрямую, без лишнего кода. Но фишка не только в лаконичности — он также автоматически пробрасывает исключения и возвращаемые значения из подгенератора.Вот классика:def gen(): for x in range(3): yield xdef wrapper(): for x in gen(): yield xМожно короче и лучше:def wrapper(): yield from gen()Но главное — yield from пробрасывает return-значение из подгенератора (начиная с Python 3.3):def sub(): yield 1 yield 2 return 'done'def main(): result = yield from sub() print('Sub returned:', result)for _ in main(): pass# Выведет: Sub returned: doneА ещё через yield from можно проксировать значения внутрь генератора — например, в сопрограммах:def delegator(): result = yield from coroutine() print('coroutine done:', result)def coroutine(): x = yield y = yield return x + yg = delegator()next(g) # Стартnext(g) # coroutine ждет xg.send(10) # x = 10print(g.send(20)) # y = 20 → return 30# Выведет: coroutine done: 30Итог: если вы пишете генераторы — освоение yield from даст вам лаконичный синтаксис, проброс return-значений, исключений и взаимодействие на новом уровне.📲 Мы в MAX👉@BookPython

2 мар. 2026 г.1 360В Telegram
Б
Библиотека Python разработчика | Книги по питону@bookpython

🚀 Подборка полезных IT каналов в MaxСистемное администрирование, DevOps 📌https://max.ru/i_odmin Все для системного администратораhttps://max.ru/bash_srv Bash Советыhttps://max.ru/sysadminof Книги для админов, полезные материалыhttps://max.ru/i_odmin_book Библиотека Системного Администратораhttps://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др.1C разработка 📌https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1СПрограммирование C++📌https://max.ru/cpp_lib Библиотека C/C++ разработчикаПрограммирование Python 📌https://max.ru/python_of Python академия. https://max.ru/BookPython Библиотека Python разработчикаJava разработка 📌https://max.ru/bookjava Библиотека Java разработчикаGitHub Сообщество 📌https://max.ru/githublib Интересное из GitHubБазы данных (Data Base) 📌https://max.ru/database_info Все про базы данныхФронтенд разработка 📌https://max.ru/frontend_1 Подборки для frontend разработчиковБиблиотеки 📌https://max.ru/programmist_of Книги по программированиюhttps://max.ru/proglb Библиотека программистаhttps://max.ru/bfbook Книги для программистовПрограммирование 📌https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференцийhttps://max.ru/itmozg Программисты, дизайнеры, новости из мира IThttps://max.ru/php_lib Библиотека PHP программиста 👨🏼‍💻👩‍💻Шутки программистов 📌https://max.ru/itumor Шутки программистовЗащита, взлом, безопасность 📌https://max.ru/thehaking Канал о кибербезопасностиhttps://max.ru/xakkep_1 Хакер FreeКниги, статьи для дизайнеров 📌https://max.ru/odesigners Статьи, книги для дизайнеровМатематика 📌https://max.ru/Pomatematike Канал по математикеhttps://max.ru/phismat_1 Обучающие видео, книги по Физике и МатематикеВакансии 📌 https://max.ru/progjob Вакансии в ITМир технологий 📌 https://max.ru/mir_teh Канал для любознательныхБонус 📌 https://max.ru/piterspb_78 Свежие новости Санкт-Петербургаhttps://max.ru/mockva_life Свежие новости Москвы

28 февр. 2026 г.1 420В Telegram
Б
Библиотека Python разработчика | Книги по питону@bookpython

Python предоставляет мощную библиотеку для работы с датой и временем — datetime. Интересный момент: объекты datetime имеют специальный интерфейс для поддержки часовых поясов (атрибут tzinfo), однако сама библиотека `datetime реализует его лишь частично, оставляя остальную работу сторонним модулям.Самым популярным модулем для этой задачи является pytz. Хитрость в том, что pytz не полностью соответствует интерфейсу tzinfo. В документации pytz прямо указано с самого начала: «Эта библиотека отличается от задокументированного API Python для реализаций tzinfo».Вы не можете просто передать объект временной зоны pytz в атрибут tzinfo. Если попробуете, результат может быть абсолютно безумным:In : paris = pytz.timezone('Europe/Paris')In : str(datetime(2017, 1, 1, tzinfo=paris))Out: '2017-01-01 00:00:00+00:09'Посмотрите на этот смещение +00:09. Правильное использование pytz выглядит так:In : str(paris.localize(datetime(2017, 1, 1)))Out: '2017-01-01 00:00:00+01:00'Кроме того, после любых операций с датой и временем, нужно нормализовать объект datetime, если есть вероятность смены смещения (например, на границе перехода на летнее время):In : new_time = time + timedelta(days=2)In : str(new_time)Out: '2018-03-27 00:00:00+01:00'In : str(paris.normalize(new_time))Out: '2018-03-27 01:00:00+02:00'Начиная с Python 3.6, рекомендуется использовать dateutil.tz вместо pytz. Он полностью совместим с tzinfo, может использоваться напрямую, не требует normalize, хотя и работает немного медленнее.Если вам интересно, почему pytz не поддерживает API datetime, или вы хотите увидеть больше примеров, обязательно почитайте хорошую статью на эту тему.📲 Мы в MAX👉@BookPython

27 февр. 2026 г.1 620В Telegram
Б
Библиотека Python разработчика | Книги по питону@bookpython

Когда вы используете модуль multiprocessing, и в одном из процессов происходит исключение, оно передаётся в основную программу с помощью механизма сериализации (pickling). Исключение сериализуется, передаётся в другой процесс и там десериализуется обратно.Однако сериализация исключений может быть непростой задачей. Исключение создаётся с любым количеством аргументов, которые сохраняются в атрибуте args. Эти же аргументы используются при десериализации для воссоздания объекта исключения.Но это может не сработать так, как вы ожидаете, особенно если используется наследование. Посмотрите на пример:import pickleclass TooMuchWeightError(Exception): def __init__(self, weight): super().__init__() self._weight = weightpickled = pickle.dumps(TooMuchWeightError(42))pickle.loads(pickled)Вызов TooMuchWeightError.__init__ приводит к вызову Exception.__init__, который устанавливает args как пустой кортеж. Этот пустой кортеж затем используется в качестве аргументов при десериализации, что, очевидно, приводит к ошибке:TypeError: __init__() missing 1 required positional argument: 'weight'Обходное решение — либо вообще не вызывать super().__init__() (что обычно считается плохой практикой при наследовании), либо передавать все аргументы явно в конструктор родительского класса:class TooMuchWeightError(Exception): def __init__(self, weight): super().__init__(weight) self._weight = weight📲 Мы в MAX👉@BookPython

26 февр. 2026 г.1 620В Telegram
Б
Библиотека Python разработчика | Книги по питону@bookpython

Функция map вызывает другую функцию для каждого элемента итерируемого объекта. Это значит, что функция должна принимать одно значение в качестве аргумента:In : list(map(lambda x: x ** 2, [1, 2, 3]))Out: [1, 4, 9]Однако если каждый элемент итерируемого объекта — это кортеж, было бы удобно передавать каждый элемент кортежа как отдельный аргумент. В Python 2 это было возможно благодаря распаковке параметров кортежа (обратите внимание на скобки):>>> map(lambda (a, b): a + b, [(1, 2), (3, 4)])[3, 7]В Python 3 эта возможность исчезла, но есть другое решение — itertools.starmap. Она распаковывает кортежи за вас, будто функция вызывается со звёздочкой: f(*arg) (отсюда и название функции):from itertools import starmapIn [3]: list(starmap(lambda a, b: a + b, [(1, 2), (3, 4)]))Out[3]: [3, 7]📲 Мы в MAX👉@BookPython

25 февр. 2026 г.1 650В Telegram
Б
Библиотека Python разработчика | Книги по питону@bookpython

Функция super() позволяет обращаться к родительскому (базовому) классу. Это может быть очень полезно в случаях, когда производный класс хочет добавить что-то к реализации метода, а не полностью переопределять его:class BaseTestCase(TestCase): def setUp(self): self._db = create_db()class UserTestCase(BaseTestCase): def setUp(self): super().setUp() self._user = create_user()Имя функции super не означает "отличный" или "очень хороший". В данном контексте слово super означает "выше" (как, например, в слове superintendent — заведующий). Несмотря на это, super() не всегда ссылается на базовый класс — он может вернуть и "соседний" класс. Более точным названием была бы, возможно, функция next(), так как возвращается следующий класс согласно цепочке разрешения методов (MRO — Method Resolution Order).Пример:class Top: def foo(self): return 'top'class Left(Top): def foo(self): return super().foo()class Right(Top): def foo(self): return 'right'class Bottom(Left, Right): pass# выводит 'right'print(Bottom().foo())Обрати внимание: результат работы super() может отличаться в зависимости от MRO вызвавшего объекта.>>> Bottom().foo()'right'>>> Left().foo()'top'📲 Мы в MAX👉@BookPython

24 февр. 2026 г.1 570В Telegram
Библиотека Python разработчика | Книги по питону — пост в ТГ канале
Б
Библиотека Python разработчика | Книги по питону@bookpython

Стандартный механизм расширения путей в оболочке называется globbing. Шаблоны, которые вы используете для сопоставления путей, называются globs.$ echo /li*/lib /lib64Python поддерживает globbing с помощью модуля glob. Однако есть важное замечание: оболочка возвращает сам шаблон, если файлы не найдены, а Python — нет:$ echo /zz**/zz**$ python -c 'from glob import glob; print(glob("/zz**"))'[]📲 Мы в MAX👉@BookPython

23 февр. 2026 г.1 650В Telegram
Б
Библиотека Python разработчика | Книги по питону@bookpython

Обычно вы взаимодействуете с генератором, запрашивая данные с помощью next(gen). В Python 3 вы также можете отправлять значения обратно в генератор с помощью g.send(x). Но существует техника, которой вы, вероятно, не пользуетесь каждый день, а возможно, и вовсе не знаете: выбрасывание исключений внутри генератора.С помощью gen.throw(e) можно выбросить исключение в той точке, где генератор gen приостановлен — то есть на инструкции yield. Если генератор обрабатывает это исключение, gen.throw(e) возвращает следующее значение, полученное через yield (или выбрасывает StopIteration, если генератор завершён). Если генератор не перехватывает исключение, оно пробрасывается обратно к вызывающему коду.def gen(): try: yield 1 except ValueError: yield 2g = gen()next(g)# Out: 1g.throw(ValueError)# Out: 2g.throw(RuntimeError('TEST'))# RuntimeError: TESTЭта техника позволяет более точно управлять поведением генератора — не только передавать данные внутрь, но и, например, сообщать о проблемах со значениями, полученными через yield. Однако такие случаи бывают редко, и встретить g.throw в дикой природе почти невозможно.Тем не менее, декоратор @contextmanager из модуля contextlib использует именно такую технику, позволяя коду внутри контекста перехватывать исключения.from contextlib import contextmanager@contextmanagerdef atomic(): print('BEGIN') try: yield except Exception: print('ROLLBACK') else: print('COMMIT')with atomic(): print('ERROR') raise RuntimeError()BEGIN ERROR ROLLBACK📲 Мы в MAX👉@BookPython

20 февр. 2026 г.1 870В Telegram

Похожие каналы