dataclasses

Время чтения: меньше 5 мин

Кратко

Секция статьи "Кратко"

Описанный в PEP557 и добавленный в версий 3.7 модуль dataclasses, упрощают создание классов, в которых в последующем хранятся некие данные. С помощью декоратора @dataclass, у нас автоматически генерируются магические методы __init__ и __repr__.

Практика

Секция статьи "Практика"

Допустим мы хотим создать класс Person, для этого нам понадобится написать следующий код:

        
          
          class Person:    def __init__(self, full_name, age = 1):        self.full_name = full_name        self.age = age    def __repr__(self):        return f"{self.__class__.__name__}(full_name='{self.full_name}', age={self.age})"
          class Person:
    def __init__(self, full_name, age = 1):
        self.full_name = full_name
        self.age = age

    def __repr__(self):
        return f"{self.__class__.__name__}(full_name='{self.full_name}', age={self.age})"

        
        
          
        
      

В случае с dataclasses, мы можем написать (очень важна аннотация типов, т.к. атрибуты без аннотаций будут проигнорированы и приведет к исключению NameError):

        
          
          from dataclasses import dataclass@dataclassclass Person:    full_name: str    age: int = 1
          from dataclasses import dataclass

@dataclass
class Person:
    full_name: str
    age: int = 1

        
        
          
        
      

А магические методы __init__ и __repr__ как и было сказано ранее, сгенерируются автоматически. Обратите внимание, мы также можем задавать значения по умолчанию для атрибутов. Однако мы можем еще упростить этот код:

        
          
          from dataclasses import make_dataclassPerson = make_dataclass("Person", ["full_name", "age"])
          from dataclasses import make_dataclass
Person = make_dataclass("Person", ["full_name", "age"])

        
        
          
        
      

Из полезного в модуле есть дополнительно методы, которые позволяют вернуть атрибуты класса в виде кортежа или словаря.

        
          
          from dataclasses import asdict, astupleprint(asdict(Person("John Doe", 20))))# {'full_name': 'John Doe', 'age': 20}
          from dataclasses import asdict, astuple
print(asdict(Person("John Doe", 20))))
# {'full_name': 'John Doe', 'age': 20}

        
        
          
        
      

С помощью параметра frozen можно закрыть изменение экземпляров dataclass-а:

        
          
          from dataclasses import dataclass@dataclass(frozen=True)class Person:    full_name: str    age: int = 1person = Person("John Doe", 20)person.email = "Doe@gmail.com"# raise dataclasses.FrozenInstanceError: cannot assign to field 'email'
          from dataclasses import dataclass

@dataclass(frozen=True)
class Person:
    full_name: str
    age: int = 1

person = Person("John Doe", 20)
person.email = "Doe@gmail.com"
# raise dataclasses.FrozenInstanceError: cannot assign to field 'email'

        
        
          
        
      

Напоследок, dataclasses - исходя из названия классы, которые можно наследовать и производить любые действия, как и с обычными классами в питоне. Ссылка для лучшего ознакомления: