Вступление

В мире компьютерного программирования существует множество методов, которые программисты используют для экономии времени. Время всегда является проблемой в мире разработки программного обеспечения, и бывает довольно сложно уложиться в сроки. В результате методы, позволяющие сэкономить время, стали довольно популярными и, что более важно, очень полезными. Хотя Python может быть быстрым языком для написания, есть несколько способов, с помощью которых процесс написания Python можно ускорить и сделать его еще быстрее. Имея это в виду, позвольте мне познакомить вас с концепцией и объектом программирования Pythonic:

Класс данных.

Классы данных в Python - это классы, которые декорируются с помощью инструмента из стандартной библиотеки. Декоратор класса данных, @dataclass, может использоваться для добавления специальных методов к пользовательским классам. Преимущество этого заключается в том, что это делается автоматически, а это означает, что вы можете немного больше сосредоточиться на функциях своего класса, а не на самом классе.

"Ноутбук"

Создание класса данных

Хотя декоратор класса данных включен в стандартную библиотеку, он, как и многие другие компоненты Python, содержится в собственном уникальном модуле. Имея это в виду, первым шагом к созданию класса данных является фактическое импортирование модуля.

import dataclass

Теперь мы можем создать новый класс, содержащий произвольные данные, и украсить этот класс декоратором @dataclass. Мы определим данные в этом классе, используя аннотации, описанные в PEP526.

from dataclasses import dataclass
@dataclass
class Food:
    name: str
    unit_price: float
    stock: int = 0
        
    def stock_value(self) -> float:
        return(self.stock * self.unit_price)

Теперь мы можем создать новый класс, вызвав этот конструктор, например:

carrot = Food("Carrot", .45, 25)

Давайте теперь посмотрим, что произошло бы, если бы мы написали тот же код без использования декоратора класса данных:

class Food:
    name: str
    unit_price: float
    stock: int = 0
        
    def stock_value(self) -> float:
        return(self.stock * self.unit_price)
carrot = Food("Carrot", .45, 25)

Мы видим, что теперь мы получаем ошибку типа при вызове этого конструктора. Это потому, что теперь наши данные просто хранятся как переменные-члены. В результате наша функция __init__ принимает форму по умолчанию. Форма по умолчанию не содержит аргументов, и это функция, которая вызывается всякий раз, когда мы пытаемся создать эти данные. Чтобы исправить это, нам нужно будет написать новую функцию __init__ для нашего класса:

class Food:
    name: str
    unit_price: float
    stock: int = 0
        
    def __init__(self, name: str, unit_price: float, stock: int):
        self.name, self.unit_price, self.stock = name, stock, unit_price
    
    def stock_value(self) -> float:
        return(self.stock * self.unit_price)

Теперь мы видим, что можем успешно создать наш тип еды:

carrot = Food("Carrot", .45, 25)

Весь код, который мы только что добавили к нашей функции, был автоматически добавлен нашим декоратором класса данных. Излишне говорить, что это довольно круто!

Почему они классные?

Теперь, когда у нас есть базовое представление о том, что делает этот декоратор, давайте рассмотрим, почему вы можете применить его к своему коду. Для начала вам нужно будет написать намного меньше специальных методов. Это может сэкономить время и повысить вашу производительность. В приведенном выше примере, если бы я не выполнил все самостоятельные назначения в одной строке, мы могли бы сохранить написание четырех строк кода. Более того, это не единственная специальная функция, которая генерируется всякий раз, когда мы вызываем декоратор класса данных. Это означает, что наш класс будет даже более убедительным, когда дело доходит до специальных функций, при написании намного меньшего количества кода.

Очень веским преимуществом использования этого декоратора является также то, что он позволяет избежать беспорядка в классах. Пример присвоения каждого отдельного значения внутри класса Python переменной-члену на самом деле невероятно распространен. На самом деле нет большой причины писать целую функцию со смехотворным количеством self.x = x, когда этого можно полностью избежать, просто используя декоратор. Это также может сделать класс более читабельным. Легко понять, почему это

@dataclass
class Food:
    name: str
    unit_price: float
    stock: int = 0
        
    def stock_value(self) -> float:
        return(self.stock * self.unit_price)

может быть намного более читаемым, чем это

class Food:
    name: str
    unit_price: float
    stock: int = 0
        
    def __init__(self, name: str, unit_price: float, stock: int):
        self.name = name
        self.stock = stock
        self.unit_price = unit_price
    
    def stock_value(self) -> float:
        return(self.stock * self.unit_price)

Кроме того, использование декоратора класса данных также позволяет сосредоточить внимание на том, где это действительно важно в этой функции. Поскольку при инициализации этого класса ничего делать не нужно, на самом деле не имеет смысла вставлять большую функцию __init__ в его середину. Основное внимание здесь следует уделять данным внутри класса и функциям, которые работают с этими данными.

Наконец, важно отметить, что это еще не все, что делает декоратор. dataclasses можно использовать для быстрого создания довольно удивительных структур, которые на удивление сложны. Мы также можем использовать классы данных в качестве подхода Pythonic, например, к данным JSON. Во многих отношениях мы можем думать о них так же, как о массивах данных в Javascript. Излишне говорить, что это очень удобно при программировании на Python. Рассмотрим этот пример:

@dataclass
class Point:
     x: int
     y: int
p = Point(10, 20)
assert dataclasses.asdict(p) == {'x': 10, 'y': 20}

Здесь мы превращаем класс в словарь, который содержит два значения внутри него. Эти два типа данных в основном стали эквивалентными, и их определение занимает примерно одинаковое время. Кажется невозможным написать класс быстрее, чем словарь, но в приведенном выше примере мы делаем именно это. Излишне говорить, что они, безусловно, пригодятся. Это особенно актуально для тех из нас, кто работает с большим количеством данных.

Заключение

Учитывая все обстоятельства, классы данных потрясающие! Если вы хотите узнать больше о классах данных, вы можете ознакомиться с PEP557, где вы найдете исчерпывающий источник информации о классах данных и работе с ними. Есть так много веских причин для внедрения их в свой код. Это не только упростит чтение кода, но и упростит его написание! Спасибо, что прочитали, и я надеюсь, что этот декоратор уведет вас далеко в ваших путешествиях по Python!