Прямой доступ к атрибутам объекта может быть не самой лучшей идеей. Если клиенты взаимодействуют с объектом через методы, вы всегда можете изменить способ обработки каждого запроса, в то время как при прямом доступе к атрибутам это может быть невозможно.
Разные языки решают эту проблему по-разному. В Ruby синтаксически невозможно получить прямой доступ к атрибуту:
Python предлагает решение, которое в некотором роде похоже на то, что есть в Ruby. Вы можете определить свойство (
📲 Мы в MAX
👉@BookPython
Разные языки решают эту проблему по-разному. В 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
👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
С версии Python 3.0 выбрасывание исключения внутри блока
Результат выполнения:
Вы также можете добавить
Результат выполнения:
📲 Мы в MAX
👉@BookPython
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!
👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Профайлинг и Оптимизация Производительности
Когда ваш код уже не просто работает, а должен летать, на первый план выходит умение профилировать и оптимизировать производительность. Для Python это не просто трюки, а глубокое понимание CPython и его инструментов.
Шаг 1: Точное Измерение (Profiling)
Прежде чем оптимизировать, мы должны знать, где именно тратятся ресурсы. Слепое улучшение кода — это путь к бессмысленным изменениям и появлению новых багов.
- Модуль
- Line-by-line Profilers (
- Анализ Памяти (
Шаг 2: Реальная Оптимизация (Beyond Simple Fixes)
Найдя узкое место, приступаем к устранению, используя знания об устройстве Python.
1. Уменьшение Накладных Расходов Интерпретатора (Interpreter Overhead)
- Использование Встроенных Функций и Модулей C: Встроенные функции (например,
- Пример: Используйте
2. Манипуляции с Данными NumPy/Pandas
- Векторизация: Если вы работаете с числовыми данными, полностью переходите на NumPy и Pandas. Вместо циклов
3. Параллелизм vs. Конкурентность
- CPU-bound задачи (расчеты): Из-за GIL (Global Interpreter Lock) чистый Python не может эффективно использовать несколько ядер ЦП для одновременного выполнения кода на Python. Используйте модуль
- I/O-bound задачи (сеть, диск): Если код проводит много времени в ожидании (ввод-вывод), используйте конкурентность с помощью
📲 Мы в MAX
👉@BookPython
Когда ваш код уже не просто работает, а должен летать, на первый план выходит умение профилировать и оптимизировать производительность. Для 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 "освобождает" его во время ожидания.👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
В Python множества поддерживают операторы сравнения, где
Это означает, что множества частично упорядочены, то есть существуют такие
Некоторые функции, такие как
📲 Мы в MAX
👉@BookPython
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}
👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Иногда вам нужно очистить коллекцию в Python. Вы, вероятно, используете что-то вроде
Правильный способ очистки словаря, множества,
📲 Мы в MAX
👉@BookPython
d = {} (для словарей), но на самом деле это не очистка, а создание новой коллекции и выбрасывание старой. Это может сработать для вас, но другие владельцы того же объекта всё ещё будут иметь ссылку на оригинальный.Правильный способ очистки словаря, множества,
deque и других коллекций — вызвать x.clear(). 👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Иногда вам может понадобиться проверить синтаксис Python-файла без его запуска. Такая простая проверка может быть полезна, например, в качестве хука перед коммитом или быстрой проверки в рамках непрерывной интеграции (CI).
Прямого способа сделать это нет. Вы можете запустить файл с помощью команды
Тем не менее, стандартная библиотека Python содержит модуль
📲 Мы в MAX
👉@BookPython
Прямого способа сделать это нет. Вы можете запустить файл с помощью команды
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
👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2👍1
CPython поддерживает два уровня оптимизации. Вы можете включить их с помощью флагов
- Флаг
- Флаг
Обычная версия скрипта кэшируется в файл
📲 Мы в MAX
👉@BookPython
-O и -OO.- Флаг
-O устанавливает __debug__ в значение False и удаляет все операторы assert из программы. - Флаг
-OO делает то же самое, а также удаляет строки документации (docstrings).Обычная версия скрипта кэшируется в файл
.pyc, а оптимизированная версия раньше кэшировалась в файл .pyo. Однако, начиная с Python 3.5, файлы .pyo больше не используются. Вместо них, в соответствии с PEP 488, вводятся файлы .opt-1.pyc и .opt-2.pyc.👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
«Reduce» — это функция высшего порядка, которая рекурсивно обрабатывает итерируемый объект, применяя некоторую операцию к следующему элементу и уже вычисленному значению. Также вы можете знать её под названиями «fold», «inject», «accumulate» или другими.
Использование
В Python функция
Также, если вам нужны простые лямбда-функции, такие как
📲 Мы в MAX
👉@BookPython
Использование
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
👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3❤1
Аффирмация:
Вселенная любит меня и не даёт мне сойти с ума.
Проговариваем это каждое утро по 5 раз, и, возможно, этот рабочий декабрь будет легче
Если и это не помогло, приходите в канал команды AvitoTech похоливарить, обсудить насущное и понять, что вы не одни
Что ещё можно найти у ребят:
экспертизу инженеров из Авито по самым разным направлениям;
полезные видео для тех, кто хочет разобраться в сложных темах в короткие сроки;
анонсы офлайн- и онлайн-митапов;
инсайты для тех, кто хочет попасть в Авито, а также анонсы стажировок и различных ивентов вроде Weekend Offer.
А где ссылка? Да вот же она.
Реклама. Рекламодатель ООО "Авито Тех". erid 2VtzqveKaga
Please open Telegram to view this post
VIEW IN TELEGRAM
Создание новой переменной в Python фактически означает создание нового имени для уже существующего объекта. Именно поэтому этот процесс называется связыванием имени (name binding).
Существует множество способов связать имя с объектом. Вот примеры того, как можно связать
Также можно привязать имя к объекту, манипулируя глобальным пространством имен:
Однако нельзя сделать то же самое с
📲 Мы в MAX
👉@BookPython
Существует множество способов связать имя с объектом. Вот примеры того, как можно связать
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() игнорируются.👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Please open Telegram to view this post
VIEW IN TELEGRAM