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

@BookPythonVerifiedLive API

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

По всем вопросам @evgenycarter

РКН clck.ru/3Ko7Hq

CategoryOtherLanguageRUFirst seenJul 06, 2026QualityVerified
Open in Telegram
Subscribers17.9K
Avg views965
ERR5.4%
Price-- RUB
Price / subscriber--
Price / view--
Metrics updated: Nov 13, 2026
Recent posts
Иногда возникает необходимость выполнить участок кода и проигнорировать все возможные исключения. Это оправдано в случае с плагинами, сторонними модулями и другими компонентами, устройство которых вам неизвестно или которым вы не доверяете.

Правильный способ сделать это — использовать конструкцию try с `except Exception`, а не голый `except`:

```
try:
foreign()
except Exception:
logging.warn('fail', exc_info=True)
```

Голый `except` эквивалентен `except BaseException`. А разница между `BaseException` и `Exception` в том, что `BaseException` включает исключения, которые, как правило, ловить не следует, например, `KeyboardInterrupt`.

📲 Мы в MAX

👉@BookPython
298Nov 12
В Python оператор квадратных скобок `[]` можно переопределить, реализовав магический метод `getitem`. Это позволяет, например, создать объект, который виртуально содержит бесконечное количество повторяющихся элементов:

```
class Cycle:
def init(self, lst):
self._lst = lst

def getitem(self, index):
return self._lst[index % len(self._lst)]

print(Cycle(['a', 'b', 'c'])[100]) # 'b'
```

Необычность оператора `[]` в Python в том, что он поддерживает особый синтаксис. Его можно использовать не только так: `[2]`, но и так: `[2:10]`, `[2:10:2]`, `[2::2]` или даже `[:]`. Смысл такой записи — `[start:stop:step]`, но в ваших собственных объектах вы можете использовать этот синтаксис как угодно.

Что же передаётся в `getitem` в таких случаях? Объекты `slice` созданы специально для этого.

Пример:

```
class Inspector:
def getitem(self, index):
print(index)

Inspector()[1]
# 1

Inspector()[1:2]
# slice(1, 2, None)

Inspector()[1:2:3]
# slice(1, 2, 3)

Inspector()[:]
# slice(None, None, None)

Inspector()[:, 0, :]
# (slice(None, None, None), 0, slice(None, None, None))
```

Объект `slice` сам по себе ничего не делает — он просто хранит атрибуты `start`, `stop` и `step`:

```
s = slice(1, 2, 3)
print(s.start) # 1
print(s.stop) # 2
print(s.step) # 3
```

📲 Мы в MAX

👉@BookPython
519Nov 12
Существует два понятия с похожими названиями, которые легко перепутать: переопределение (overriding) и перегрузка (overloading).

Переопределение происходит, когда дочерний класс определяет метод, который уже был реализован в родительском классе, фактически заменяя его. В некоторых языках необходимо явно указывать, что метод переопределяется (например, в C# используется модификатор `override`), в других — это необязательно (в Java можно, но не обязательно использовать аннотацию `@Override`). В Python нет ни обязательного, ни стандартного способа обозначать такие методы (некоторые программисты применяют пользовательский декоратор `@override`, который ничего не делает, а служит только для читаемости кода).

Перегрузка, напротив, — это наличие нескольких функций с одним и тем же именем, но разными сигнатурами. Это поддерживается в таких языках, как Java и C++, и часто используется как способ предоставления значений по умолчанию:

```
class Foo {
public static void main(String[] args) {
System.out.println(Hello());
}

public static String Hello() {
return Hello("world");
}

public static String Hello(String name) {
return "Hello, " + name;
}
}
```

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

```
def quadrilateral_area(*args):
if len(args) == 4:
quadrilateral = Quadrilateral(*args)
elif len(args) == 1:
quadrilateral = args[0]
else:
raise TypeError()

return quadrilateral.area()
```

Если вам нужны подсказки типов для такой реализации, модуль `typing` предоставляет декоратор `@overload`, который можно использовать следующим образом:

```
from typing import overload

@overload
def quadrilateral_area(
q: Quadrilateral
) -> float: ...

@overload
def quadrilateral_area(
p1: Point, p2: Point,
p3: Point, p4: Point
) -> float: ...
```

📲 Мы в MAX

👉@BookPython
670Nov 10
🚀 Как логировать без боли в Python

Как настроить логирование в Python один раз — и больше к этому не возвращаться.

Обычно начинающие разработчики либо используют `print()`, либо подключают `logging`, но каждый раз пишут кучу однотипного кода. Я так тоже делал. Но потом вывел себе простую универсальную схему, которую теперь кидаю в каждый новый проект:

```
import logging

def setup_logger(name: str) -> logging.Logger:
logger = logging.getLogger(name)
if not logger.hasHandlers():
logger.setLevel(logging.INFO)
handler = logging.StreamHandler()
formatter = logging.Formatter(
'%(asctime)s - %(levelname)s - %(name)s - %(message)s'
)
handler.setFormatter(formatter)
logger.addHandler(handler)
return logger

logger = setup_logger(name)

logger.info("Скрипт стартовал")
```

Что мы получаем:

* Удобный формат времени и уровня лога
* Защиту от дублирования логов (если модуль импортируется несколько раз)
* Готовность к масштабированию (можно легко добавить файл-логгер)

Если вы устали от `print()`, просто сохраните себе этот сниппет — он сэкономит вам время и нервы.

Пользуетесь ли вы встроенным `logging`, или предпочитаете что-то вроде `loguru`?

📲 Мы в MAX

👉@BookPython
763Nov 9
💡 Как избежать повторения кода с помощью `functools.partial`

Как упростить код и избежать дублирования с помощью `functools.partial`.

Допустим, у нас есть функция `send_email(to, subject, body, is_html=False)`, и мы часто вызываем её с одним и тем же параметром `is_html=True`.

Вместо того чтобы каждый раз писать это явно, можно создать частичную функцию:

```
from functools import partial

send_html_email = partial(send_email, is_html=True)

# Теперь можно вызывать проще:
send_html_email("user@example.com", "Привет", "Как дела?")
```

Это удобно, если вы хотите предварительно зафиксировать часть аргументов, например:

* логгеры с предустановленным уровнем
* коннекторы с общими параметрами
* команды CLI с типовыми флагами

Таким образом, вы уменьшаете дублирование и делаете код читаемее. А ещё это красивый способ внедрить DI без фреймворков — просто передайте `partial`.

📲 Мы в MAX

👉@BookPython
952Nov 6