Модуль dataclass. Data-классы

Последнее обновление: 27.03.2024

Модуль dataclasses предоставляет декоратор dataclass, который позволяет создавать data-классы - подобные позволяют значительно сократить шаблонный код классов. Как правило, такие классы предназначены для хранения некоторого состояния, некоторых данных и когда не требуется какое-то поведение в виде функций.

Рассмотрим простейший пример:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

tom = Person("Tom", 38)
print(f"Name: {tom.name}  Age: {tom.age}")      # Name: Tom  Age: 38

Здесь определен класс Person, у которого в функции конструктора определены два атрибута: name и age. Далее создаем один объект этого класса и выводим значения его атрибутов на консоль.

Теперь изменим эту программу, сделав класс Person data-классом:

from dataclasses import dataclass

@dataclass
class Person:
    name: str
    age: int

tom = Person("Tom", 38)
print(f"Name: {tom.name}  Age: {tom.age}")      # Name: Tom  Age: 38

Для создания data-класса импортируем из модуля dataclasses декоратор dataclass и применяем его к классу Person. И в этом случае в самом классе нам уже не надо указывать конструктор - функцию __init__. Мы просто указываем атрибуты. А Python потом сам сгенерирует конструктор, в который также мы можем передать значения для атрибутов объекта.

Таким образом, мы уже сократили определение класса и сделали его более простым. Но генерацией метода __init__ функциональность декоратора dataclass не ограничивается. В реальности data-класс

@dataclass
class Person:
    name: str
    age: int

будет аналогичен следующему:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __repr__(self):
        return f"Person(name={self.name!r}, age={self.age!r}"
    
    def __eq__(self, other):
        if other.__class__ is self.__class__:
            return (self.name, self.age) == (other.name, other.age)
        return NotImplemented

В данном случае мы видим, что кроме функции __init__, также определяется функция __repr__() для возвращения строкового представления и функция __eq__() для сравнения двух объектов. Применение данных функций:

from dataclasses import dataclass

@dataclass
class Person:
    name: str
    age: int


tom = Person("Tom", 38)
bob = Person("Bob", 42)
tomas = Person("Tom", 38) 
print(tom == tomas)     # True
print(tom == bob)       # False
print(tom)              # Person(name="Tom", age=38)

Параметры декоратора dataclass

С помощью параметров декоратор dataclass позволяет сгенерировать дополнительный шаблонный код и вообще настроить генерацию кода:

def dataclass(cls=None, /, *, init=True, repr=True, eq=True, order=False,
              unsafe_hash=False, frozen=False, match_args=True,
              kw_only=False, slots=False)

Рассмотрим базовые параметры:

  • init: если равно True, то генерируется функция __init__(). По умолчанию равно True

  • repr: если равно True, то генерируется функция __repr__(), которая возвращает строковое представление объекта. По умолчанию равно True

  • eq: если равно True, то генерируется функция __eq__(), которая сравнивает два объекта. По умолчанию равно True

  • order: если равно True, то генерируются функции __lt__ (операция <), __le__ (<=), __gt__ (>), __ge__ (>=), которые применяются для упорядочивания объектов. По умолчанию равно False

  • unsafe_hash: если равно True, то генерируется функция __hash__(), которая возвращает хеш объекта. По умолчанию равно False

Кроме того, те функции, которые создаются по умолчанию, могут быть переопределены.

Применение параметров:

from dataclasses import dataclass

@dataclass(unsafe_hash=True, order=True)
class Person:
    name: str
    age: int
    def __repr__(self):
        return f"Person. Name: {self.name}  Age: {self.age}"


tom = Person("Tom", 38)
print(tom.__hash__())   # -421667297069596717
print(tom)              # Person. Name: Tom  Age: 38

В данном случае включаем генерирование хеша и функций упорядочивания, а также явным образом переопределяем функцию __repr__ для создания строкового представления объекта.

значения по умолчанию

При необходимости атрибутам можно присвоить значения по умолчанию, если в конструкторе им не передаются значения:

from dataclasses import dataclass

@dataclass
class Person:
    name: str
    age: int = 18


tom = Person("Tom", 38)
print(tom)              # Person(name="Tom", age=38)

bob = Person("Bob")
print(bob)              # Person(name="Bob", age=18)

Добавление дополнительного функционала

Хотя data-классы предназначены прежде всего для хранения различных данных, но также в них можно определять поведение с помощью дополнительных функций:

from dataclasses import dataclass

@dataclass
class Person:
    name: str
    age: int

    def say_hello(self):
        print(f"{self.name} says hello")


tom = Person("Tom", 38)
tom.say_hello()     # Tom says hello
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850