Библиотека Python разработчика | Книги по питону – Telegram
Библиотека Python разработчика | Книги по питону
18.9K subscribers
1.06K photos
403 videos
82 files
1.05K links
Полезные материалы для питониста по Фреймворкам Django, Flask, FastAPI, Pyramid, Tornado и др.

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

РКН clck.ru/3Ko7Hq
Download Telegram
Прямой доступ к атрибутам объекта может быть не самой лучшей идеей. Если клиенты взаимодействуют с объектом через методы, вы всегда можете изменить способ обработки каждого запроса, в то время как при прямом доступе к атрибутам это может быть невозможно.

Разные языки решают эту проблему по-разному. В Ruby синтаксически невозможно получить прямой доступ к атрибуту: obj.x — это вызов метода x. В Java рекомендуется делать все атрибуты приватными и писать тривиальные геттеры, например: public int getX() { return this.x; }.

Python предлагает решение, которое в некотором роде похоже на то, что есть в Ruby. Вы можете определить свойство (property), чтобы obj.x вызывал метод вместо прямого возврата атрибута x.


class Example:
def __init__(self, x):
self._x = x

@property
def x(self):
return self._x


📲 Мы в MAX

👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
С версии Python 3.0 выбрасывание исключения внутри блока except автоматически добавляет перехваченное исключение в атрибут __context__ нового исключения. Это приводит к тому, что оба исключения отображаются в traceback:


try:
1 / 0
except ZeroDivisionError:
raise ValueError('Zero!')


Результат выполнения:


Traceback (most recent call last):
File "test.py", line 2, in <module>
1 / 0
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "test.py", line 4, in <module>
raise ValueError('Zero!')
ValueError: Zero!


Вы также можете добавить __cause__ к любому исключению с помощью выражения raise ... from:


division_error = None

try:
1 / 0
except ZeroDivisionError as e:
division_error = e

raise ValueError('Zero!') from division_error


Результат выполнения:


Traceback (most recent call last):
File "test.py", line 4, in <module>
1 / 0
ZeroDivisionError: division by zero

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "test.py", line 8, in <module>
raise ValueError('Zero!') from division_error
ValueError: Zero!


📲 Мы в MAX

👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Профайлинг и Оптимизация Производительности

Когда ваш код уже не просто работает, а должен летать, на первый план выходит умение профилировать и оптимизировать производительность. Для Python это не просто трюки, а глубокое понимание CPython и его инструментов.

Шаг 1: Точное Измерение (Profiling)

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

- Модуль cProfile: Стандартный и самый надежный инструмент для нахождения горячих точек (hotspots) — функций, где тратится больше всего времени. Он показывает совокупное время (tottime) и общее время (cumtime) выполнения каждой функции, включая вызовы извне.


import cProfile
import re

cProfile.run('re.compile("foo|bar")', filename='profile_data')
# Анализируем результаты
import pstats
p = pstats.Stats('profile_data')
p.sort_stats('cumulative').print_stats(10)


- Line-by-line Profilers (line_profiler): Если cProfile показывает функцию, которая "тормозит", но вам нужно понять, какая именно строка внутри этой функции виновата, используйте внешние инструменты, такие как line_profiler.


# Декоратор @profile над нужной функцией
# Запуск: kernprof -l my_noscript.py
# Анализ: python -m line_profiler my_noscript.py.lprof


- Анализ Памяти (memory_profiler): Для задач, связанных с большими данными или длительными процессами, где утечки памяти или излишнее потребление критичны, используйте memory_profiler или pympler.


Шаг 2: Реальная Оптимизация (Beyond Simple Fixes)

Найдя узкое место, приступаем к устранению, используя знания об устройстве Python.

1. Уменьшение Накладных Расходов Интерпретатора (Interpreter Overhead)

- Использование Встроенных Функций и Модулей C: Встроенные функции (например, sum, map, sorted) и функции из стандартной библиотеки, написанные на C (например, itertools, collections), работают значительно быстрее, чем их эквиваленты на чистом Python, поскольку избегают накладных расходов на GIL и байткод.
- Пример: Используйте collections.deque вместо list для быстрого добавления/удаления с обоих концов.

2. Манипуляции с Данными NumPy/Pandas

- Векторизация: Если вы работаете с числовыми данными, полностью переходите на NumPy и Pandas. Вместо циклов for в Python, обрабатывающих элементы по одному, используйте векторизованные операции. Это позволяет выполнять вычисления на уровне C/Fortran, эффективно используя процессор.

3. Параллелизм vs. Конкурентность

- CPU-bound задачи (расчеты): Из-за GIL (Global Interpreter Lock) чистый Python не может эффективно использовать несколько ядер ЦП для одновременного выполнения кода на Python. Используйте модуль multiprocessing для распараллеливания задачи между процессами.
- I/O-bound задачи (сеть, диск): Если код проводит много времени в ожидании (ввод-вывод), используйте конкурентность с помощью asyncio (асинхронный ввод-вывод) или threading. В этом случае GIL не мешает, так как Python "освобождает" его во время ожидания.


📲 Мы в MAX

👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
В Python множества поддерживают операторы сравнения, где a < b означает, что a является подмножеством b:


>>> {1} < {1, 2}
True
>>> {1} < {2, 3}
False


Это означает, что множества частично упорядочены, то есть существуют такие a и b, что и a < b, и b < a — ложны:


>>> {1} < {2, 3}
False
>>> {1} > {2, 3}
False


Некоторые функции, такие как min, max и sorted, требуют полного порядка, поэтому их применение к списку множеств может дать неожиданные результаты:


>>> min([{1}, {2}])
{1}
>>> min([{2}, {1}])
{2}


📲 Мы в MAX

👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Иногда вам нужно очистить коллекцию в Python. Вы, вероятно, используете что-то вроде d = {} (для словарей), но на самом деле это не очистка, а создание новой коллекции и выбрасывание старой. Это может сработать для вас, но другие владельцы того же объекта всё ещё будут иметь ссылку на оригинальный.

Правильный способ очистки словаря, множества, deque и других коллекций — вызвать x.clear().


📲 Мы в MAX

👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Иногда вам может понадобиться проверить синтаксис Python-файла без его запуска. Такая простая проверка может быть полезна, например, в качестве хука перед коммитом или быстрой проверки в рамках непрерывной интеграции (CI).

Прямого способа сделать это нет. Вы можете запустить файл с помощью команды python -m module.py, что предотвратит выполнение блока if __name__ == '__main__'. Однако все импорты всё равно будут выполнены, и это может привести к ошибкам, если вы хотите проверить синтаксис в среде, где модуль не может и не должен быть запущен.

Тем не менее, стандартная библиотека Python содержит модуль py_compile, который генерирует байт-код из исходного файла Python без его выполнения. Это именно то, что нам нужно:


$ python -m py_compile test.c
File "test.c", line 1
int main() {
^
SyntaxError: invalid syntax


📲 Мы в MAX

👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍1
CPython поддерживает два уровня оптимизации. Вы можете включить их с помощью флагов -O и -OO.

- Флаг -O устанавливает __debug__ в значение False и удаляет все операторы assert из программы.
- Флаг -OO делает то же самое, а также удаляет строки документации (docstrings).

Обычная версия скрипта кэшируется в файл .pyc, а оптимизированная версия раньше кэшировалась в файл .pyo. Однако, начиная с Python 3.5, файлы .pyo больше не используются. Вместо них, в соответствии с PEP 488, вводятся файлы .opt-1.pyc и .opt-2.pyc.

📲 Мы в MAX

👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
«Reduce» — это функция высшего порядка, которая рекурсивно обрабатывает итерируемый объект, применяя некоторую операцию к следующему элементу и уже вычисленному значению. Также вы можете знать её под названиями «fold», «inject», «accumulate» или другими.

Использование reduce с result = result + element даёт сумму всех элементов, result = min(result, element) возвращает минимум, а result = element позволяет получить последний элемент последовательности.

В Python функция reduce доступна (начиная с Python 3, она была перемещена в functools.reduce):


from functools import reduce

print(reduce(lambda s, i: s + i, range(10))) # 45
print(reduce(lambda s, i: min(s, i), range(10))) # 0
print(reduce(lambda s, i: i, range(10))) # 9


Также, если вам нужны простые лямбда-функции, такие как lambda a, b: a + b, в Python есть модуль operator, который упрощает их использование:


from operator import add
print(reduce(add, range(10))) # 45


📲 Мы в MAX

👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍31
🎨🎨
🎨🎨🎨🎨
🎨🎨🎨🎨
🎨🎨🎨🎨
🎨🎨🎨🎨
🎨🎨🎨🎨
Аффирмация:
В этот декабрь я привлекаю только действительно важные задачи. Я достоин уйти на праздники в спокойствии и без желания уволиться в 2026-м. Я благодарен за возможности удалённой работы, и пусть всё останется так и далее. Я единственный хозяин своего настоящего и будущего. Я с удовольствием провожу время на дейликах.
Вселенная любит меня и не даёт мне сойти с ума.

Проговариваем это каждое утро по 5 раз, и, возможно, этот рабочий декабрь будет легче

Если и это не помогло, приходите в канал команды AvitoTech похоливарить, обсудить насущное и понять, что вы не одни🚀ㅤㅤ

Что ещё можно найти у ребят:
экспертизу инженеров из Авито по самым разным направлениям;
полезные видео для тех, кто хочет разобраться в сложных темах в короткие сроки;
анонсы офлайн- и онлайн-митапов;
инсайты для тех, кто хочет попасть в Авито, а также анонсы стажировок и различных ивентов вроде Weekend Offer.

А где ссылка? Да вот же она.

Реклама. Рекламодатель ООО "Авито Тех". erid 2VtzqveKaga
Please open Telegram to view this post
VIEW IN TELEGRAM
Создание новой переменной в Python фактически означает создание нового имени для уже существующего объекта. Именно поэтому этот процесс называется связыванием имени (name binding).

Существует множество способов связать имя с объектом. Вот примеры того, как можно связать x:


x = y # Присваивание
import x # Импорт модуля
class x: pass # Определение класса
def x(): pass # Определение функции
def y(x): pass # Определение аргумента функции
for x in y: pass # Перебор элементов в цикле
with y as x: pass # Использование в конструкции with
except y as x: pass # Обработка исключения


Также можно привязать имя к объекту, манипулируя глобальным пространством имен:


In : x
NameError: name 'x' is not defined # Ошибка: переменная x не определена

In : globals()['x'] = 42 # Присваивание через globals()
In : x
Out: 42 # Теперь x привязан к 42


Однако нельзя сделать то же самое с locals(), так как изменения словаря locals() игнорируются.

📲 Мы в MAX

👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3