Мастерство Python Attrs: создание продвинутых дата-классов с практическими примерами
Пакет Python Attrs позволяет создавать продвинутые дата-классы с использованием простых аннотаций. Конечно, у Python есть свой нативный модуль dataclass, но пакет Python attrs предлагает пару дополнительных функций, которые вам могут понравиться!
Содержание
Установка attrs
Пакет attrs не входит в базовую библиотеку, поэтому вам нужно установить его с командой pip install или чем-то похожим, как Pipenv. Вы, вероятно, также захотите создать виртуальное окружение, чтобы не мешать другим проектам. Пакет называется attrs, поэтому установка будет выглядеть так:
$ pip install attrs # или с pipenv: $ pipenv install attrs
Attrs vs дата-классы
Авторы attrs на самом деле работали над PEP, который ввел дата-классы в Python. Нативные дата-классы Python намеренно держатся проще и легче для понимания, в то время как attrs предлагает полный спектр функций, которые вы можете захотеть!
Некоторые причины выбрать Python attrs вместо встроенных дата-классов:
- Вы используете версию Python до 3.7. Attrs покрывает вас, так как поддерживает все основные версии Python, включая CPython 2.7 и PyPy.
- Вы хотите больше функций: attrs предлагает валидаторы и конвертеры
- Вы хотите оптимальную производительность и минимальное использование памяти с attrs slotted-классами
Базовый пример Python attrs
Давайте посмотрим на очень базовый пример сначала:
import attr
@attr.s
class Person(object):
name = attr.ib(default='John')
surname = attr.ib(default='Doe')
age = attr.ib(init=False)
p = Person()
print(p)
p = Person('Bill', 'Gates')
p.age = 60
print(p)
# Output:
# Person(name='John', surname='Doe', age=NOTHING)
# Person(name='Bill', surname='Gates', age=60)
Пара наблюдений:
- Синтаксис менее элегантный и более многословный, чем у дата-классов, но вы получаете дополнительные функции в обмен.
- Похоже на дата-классы, вы получаете красивое форматированное представление ваших данных при печати.
- Пакет attrs использует умно подобранные имена вроде
attr.ib, поэтому вам нужно только импортировать attr. Альтернативно можно импортировать полные имена. Например, сfrom attr import attrib, attrs, и использовать эти имена вместо. Функциональность та же.
Далее посмотрим на самые важные функции, которые этот пакет предлагает над обычными дата-классами: валидаторы и конвертеры.
Пример валидатора Python attrs
Вы можете добавить валидаторы к вашему attrs дата-классу двумя способами:
- Используя декоратор
- Предоставляя вызываемую функцию
Я продемонстрирую метод вызываемой функции здесь сначала. Attrs предлагает несколько валидаторов из коробки, из которых мы используем валидатор instance_of в следующем примере:
>>> @attr.s
... class C(object):
... x = attr.ib(validator=attr.validators.instance_of(int))
>>> C(42)
C(x=42)
>>> C("a string")
Traceback (most recent call last):
... TypeError: ("'x' must be <type 'int'> (got 'a string' that is a <type 'str'>).", ...
Так как мы пытались создать объект C со строковым значением для x, валидатор instance_of выбрасывает ошибку, потому что он требует int тип вместо строки.
Давайте теперь определим свой валидатор:
import attr
@attr.s
class DividableByTwo(object):
x = attr.ib()
@x.validator
def check(self, attribute, value):
if value % 2 != 0:
raise ValueError(f'{value} is not dividable by 2')
print (DividableByTwo(60))
print (DividableByTwo(11))
# Output будет что-то вроде:
# DividableByTwo(x=60)
# ...
# ValueError: 11 is not dividable by 2
Пример конвертера Python attrs
Конвертер берет устанавливаемое значение и автоматически конвертирует его. Вы можете использовать это для всех видов целей. Один пример — автоматическая конвертация значения в int. Опять начнем с использования вызываемой функции, в этом случае просто используем Python-функцию int():
import attr
@attr.s
class C(object):
x = attr.ib(converter=int)
c = C("1")
print(c)
# Output:
# C(x=1)
Наш ввод (строка «1») был автоматически конвертирован в целое число. Потому что конвертеры запускаются до валидаторов, вы можете валидировать финальное значение после конвертации. Например, вы могли бы скомбинировать вышеуказанные два примера, чтобы сначала конвертировать любой ввод в int, а затем проверить, делится ли значение на два.
Использование slots с Python attrs
Наконец, вы можете сказать attrs использовать slotted-классы. Slotted-классы имеют некоторые преимущества над обычными классами:
- У них небольшой memory footprint
- Они быстрее
Короче, с slotted-классом вы явно указываете, какие атрибуты экземпляра вы ожидаете у ваших объектов-экземпляров. Таким образом, Python может опустить некоторые проверки и так далее, что приводит к меньшему использованию памяти и небольшому повышению скорости. Больше деталей можно найти в документации attrs.
Однако slotted-классы приходят с оговорками тоже, особенно когда вы создаете их вручную. К счастью, attrs предлагает нам простой способ включить эту функцию:
import attr
@attr.s(slots=True)
class YourClassName:
...
Продолжайте учиться
- Наша статья о Python дата-классах
- Наше руководство по Python классам и объектам
- Для больше примеров, проверьте страницу примеров attrs
Python
- Освоение типов данных в Python: практическое руководство
- Мастерство метода strip() в Python: подробное руководство и практические примеры
- Мастерство метода str.count() в Python: как подсчитывать символы и подстроки с примерами
- Функция round() в Python: подробное объяснение с практическими примерами
- Освоение функции map() в Python: синтаксис, примеры и лучшие практики
- Python timeit(): измерение времени выполнения с практическими примерами
- Counter в collections Python: эффективное подсчёт, обновление и арифметические операции
- Python time.sleep(): как добавить задержки в код (пример)
- Python list.count(): экспертное руководство с практическими примерами
- Python list.index(): как находить позиции элементов — практические примеры