Погружение в CPython и архитектуру. Разбираем неочевидное поведение (GIL, Memory), Best Practices (SOLID, DDD) и тонкости Django/FastAPI. Решаем задачи с подвохом и оптимизируем алгоритмы. 🐍
Иногда возникает необходимость выполнить участок кода и проигнорировать все возможные исключения. Это оправдано в случае с плагинами, сторонними модулями и другими компонентами, устройство которых вам неизвестно или которым вы не доверяете.
Правильный способ сделать это — использовать конструкцию try с `except Exception`, а не голый `except`:
Голый `except` эквивалентен `except BaseException`. А разница между `BaseException` и `Exception` в том, что `BaseException` включает исключения, которые, как правило, ловить не следует, например, `KeyboardInterrupt`.
В Python оператор квадратных скобок `[]` можно переопределить, реализовав магический метод `getitem`. Это позволяет, например, создать объект, который виртуально содержит бесконечное количество повторяющихся элементов:
``` class Cycle: def init(self, lst): self._lst = lst
Необычность оператора `[]` в Python в том, что он поддерживает особый синтаксис. Его можно использовать не только так: `[2]`, но и так: `[2:10]`, `[2:10:2]`, `[2::2]` или даже `[:]`. Смысл такой записи — `[start:stop:step]`, но в ваших собственных объектах вы можете использовать этот синтаксис как угодно.
Что же передаётся в `getitem` в таких случаях? Объекты `slice` созданы специально для этого.
Пример:
``` class Inspector: def getitem(self, index): print(index)
Существует два понятия с похожими названиями, которые легко перепутать: переопределение (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"); }
Python не поддерживает поиск функций по сигнатурам, только по именам. Вы можете написать код, который явно анализирует типы и количество аргументов, но это обычно выглядит громоздко и не очень красиво:
Если вам нужны подсказки типов для такой реализации, модуль `typing` предоставляет декоратор `@overload`, который можно использовать следующим образом:
Как настроить логирование в Python один раз — и больше к этому не возвращаться.
Обычно начинающие разработчики либо используют `print()`, либо подключают `logging`, но каждый раз пишут кучу однотипного кода. Я так тоже делал. Но потом вывел себе простую универсальную схему, которую теперь кидаю в каждый новый проект:
* Удобный формат времени и уровня лога * Защиту от дублирования логов (если модуль импортируется несколько раз) * Готовность к масштабированию (можно легко добавить файл-логгер)
Если вы устали от `print()`, просто сохраните себе этот сниппет — он сэкономит вам время и нервы.
Пользуетесь ли вы встроенным `logging`, или предпочитаете что-то вроде `loguru`?