Введение
Если вы только начали или уже программировали с использованием Python и любите объектно-ориентированное программирование, но не знакомы с модулем dataclasses
, вы пришли в нужное место!
В этой статье мы узнаем:
- Что такое классы данных и в чем их преимущества.
- Чем именно они отличаются от обычных классов Python.
- И когда их следует использовать.
Справочная информация о классах данных
Классы данных используются в основном для моделирования данных в Python. Он украшает обычные классы Python и не имеет ограничений, что означает, что он может вести себя как типичный класс.
Небольшой пример класса данных:
from dataclasses import dataclass
@dataclass class Car: color: str manufacturer: str top_speed_km: int
dataclasses
был введен в Python 3.7 как часть PEP 557.
Давайте погрузимся в некоторые примеры кода
Преимущества класса данных
Встроенная реализация специальных методов
При использовании декоратора @dataclass нам не нужно самим реализовывать специальные методы, что помогает нам избежать шаблонного кода, например, метода init (_init_), метод строкового представления (_repr_), методы, используемые для упорядочения объектов (например, lt, le, gt > и ge), они сравнивают класс, как если бы он был кортежем его полей, по порядку.
Прочтите о нескольких других дополнительных встроенных функциях. методы в официальной документации.
Как это будет выглядеть с обычным классом:
class Car: color: str manufacturer: str top_speed_km: int
def __init__(self, color: str, manufacturer: str, top_speed_km: bool): self.color = color self.manufacturer = manufacturer self.top_speed_km = top_speed_km
def __lt__(self, other_car): return self.top_speed_km < other_car.top_speed_km
red_ferrari = Car(color='red', manufacturer='Ferrari', top_speed_km=320) print(red_ferrari) # <__main__.Car object at 0x7f218789ca00> black_ferrari = Car(color='red', manufacturer='Ferrari', top_speed_km=347) print(red_ferrari < black_ferrari) # True
Обратите внимание на эти два момента:
- Поскольку мы не реализовали специальный метод _repr_, при печати экземпляра Car мы получаем имя класса и адрес объекта.
- Чтобы сравнить два экземпляра Car, мне пришлось реализовать метод «меньше чем» (_lt_) самостоятельно.
Пример с декоратором класса данных:
from dataclasses import dataclass
@dataclass(order=True) class Car: color: str manufacturer: str top_speed_km: int
slow_tesla = Car(top_speed_km=261, color='white', manufacturer='Tesla') print(slow_tesla) # Car(color='white', manufacturer='Tesla', top_speed_km=261) fast_tesla = Car(top_speed_km=280, color='white', manufacturer='Tesla') print(slow_tesla < fast_tesla) # True
Необходимо установить order=True
, если мы хотим, чтобы реализация методов специального порядка была включена в класс данных (например, lt)
- Когда мы пытаемся напечатать объект
slow_tesla
, мы видим фактические значения объекта, а не адрес объекта, в отличие от предыдущего примера. - Мы можем сравнивать два объекта без необходимости реализации специальных методов.
Наследование
Как и в случае с обычными классами Python, наследование здесь тоже может принести нам пользу, не нужно иметь дело с конструкцией родительского класса:
from dataclasses import dataclass
@dataclass class Car: color: str manufacturer: str top_speed_km: int
@dataclass class ElectricCar(Car): battery_capacity_kwh: int maximum_range_km: int
white_tesla_model_3 = ElectricCar(color='white', manufacturer='Tesla', top_speed_km=261, battery_capacity_kwh=50, maximum_range_km=455)
print(white_tesla_model_3) # ElectricCar(color='white', manufacturer='Tesla', top_speed_km=261, battery_capacity_kwh=50, maximum_range_km=455)
Просто для справки, вот как это будет выглядеть при использовании обычного класса:
class Car: color: str manufacturer: str top_speed_km: int
def __init__(self, color: str, manufacturer: str, top_speed_km: int): self.color = color self.manufacturer = manufacturer self.top_speed_km = top_speed_km
class ElectricCar(Car): battery_capacity_kwh: int maximum_range_km: int
def __init__(self, color: str, manufacturer: str, top_speed_km: int, battery_capacity_kwh: int, maximum_range_km: int): super().__init__(color, manufacturer, top_speed_km) self.battery_capacity_kwh = battery_capacity_kwh self.maximum_range_km: maximum_range_km
white_tesla_model_3 = ElectricCar(color='white', manufacturer='Tesla', top_speed_km=261, battery_capacity_kwh=50, maximum_range_km=455) print(white_tesla_model_3)
Надеюсь, вы видите, что мы сэкономили много стандартного кода даже в этом маленьком фрагменте кода и не повторяли инициализацию каждого параметра.
Замороженные экземпляры
Передавая frozen=True
декоратору класса данных, мы можем создавать неизменяемые объекты Python.
from dataclasses import dataclass
@dataclass(frozen=True) class Car: color: str manufacturer: str top_speed_km: int
white_tesla = Car(color='white', manufacturer='Tesla', top_speed_km=261) white_tesla.color = 'Red'
Попытка изменить white_tesla
на красную теслу выдаст нам сообщение об ошибке FrozenInstanceError:
dataclasses.FrozenInstanceError: cannot assign to field 'color'
Примечание. Использование замороженных экземпляров немного снизит производительность, поэтому используйте его осторожно.
Теперь ваша очередь:
- Знакомы с тем, что такое класс данных и как его использовать.
- Узнали о преимуществах и вариантах использования классов данных.
- Имейте несколько примеров кода, которые помогут вам начать работу.
- Можете начать использовать его в своих проектах.
Заключение
dataclasses
— это мощный модуль, который помогает нам, разработчикам Python, моделировать наши данные, избегать написания стандартного кода и писать гораздо более чистый и элегантный код.
Я призываю вас изучить и узнать больше о специальных функциях класса данных, я использую его во всех моих проектах, и я рекомендую вам сделать это тоже.
Дополнительные ресурсы
https://docs.python.org/3/library/dataclasses.html
https://realpython.com/python-data-classes/