В этой статье будет рассмотрено руководство по использованию новых объектов «dataclass», включенных в Python 3.7 и более новые версии. Классы данных похожи на другие классы Python, но они специально разработаны для использования в качестве контейнеров данных и обеспечивают более чистый и короткий синтаксис для быстрого создания объектов данных. Если вы знаете об объектах namedtuple и использовали их в Python, вы можете определить их как изменяемые объекты типа namedtuple. Вы можете создавать новые экземпляры классов данных, как любой другой класс или объекты типа namedtuple, и получать доступ к их атрибутам, используя точечную нотацию.
Базовый синтаксис и использование
Чтобы понять класс данных и его синтаксис, вам необходимо сначала понять базовую компоновку и структуру класса Python. Ниже приведен пример, показывающий простой класс Python:
class StockInHand: def __init__(self, apples, oranges, mangoes): self.apples = apples self.oranges = oranges self.mangoes = mangoes stock = StockInHand(40, 50 , 60) print (stock.apples, stock.oranges, stock.mangoes)
В приведенном выше примере кода был создан новый класс с именем «StockInHand» с определенным внутри него методом «__init__». Метод __init__ автоматически вызывается всякий раз, когда вы создаете новый экземпляр класса StockInHand. В этом случае метод __init__ был определен с некоторыми обязательными аргументами. Таким образом, вы не можете создать новый экземпляр StockInHand без некоторых значений необходимых аргументов. Аргумент «self» предоставляет ссылку на экземпляр класса, поэтому вы можете использовать его для ссылки на любую переменную или метод внутри класса, если эти переменные и методы были определены с использованием аргумента self. Аргумент self действует как удобный инструмент, и его можно назвать как угодно. Вы также можете полностью его опустить.
После выполнения приведенного выше примера кода вы должны получить следующий результат:
40 50 60
Тот же класс можно определить с помощью класса данных следующим образом:
from dataclasses import dataclass @dataclass class StockInHand: apples: int oranges: int mangoes: int stock = StockInHand(40, 50 , 60) print (stock.apples, stock.oranges, stock.mangoes)
Первый оператор импортирует декоратор «dataclass» из модуля «dataclasses». Декораторы можно использовать для изменения поведения объектов Python без их фактического изменения. В этом случае декоратор классов данных предопределен и поступает из модуля классов данных. Чтобы определить класс данных, вам необходимо присоединить декоратор класса данных с помощью символа «@» к классу Python, как показано в приведенном выше примере кода. В следующих нескольких операторах переменные в классе данных определяются с помощью подсказок типа, чтобы указать, к какому типу они относятся. Подсказки типа были введены в Python 3.6 и определены с помощью символов «:» (двоеточие). Вы можете создать новый экземпляр класса данных, как любой другой класс Python. После выполнения приведенного выше примера кода вы должны получить следующий результат:
40 50 60
Обратите внимание, что если метод в классе данных возвращает значение, вы можете назначить ему подсказку типа, используя символ «->». Вот пример:
from dataclasses import dataclass @dataclass class StockInHand: apples: int oranges: int mangoes: int def total_stock(self) -> int: return self.apples + self.oranges + self.mangoes stock = StockInHand(40, 50 , 60) print (stock.total_stock())
Был создан новый метод под названием «total_stock», и ему была назначена подсказка типа с использованием зарезервированного ключевого слова «int» для указания типа возвращаемого значения. После выполнения приведенного выше примера кода вы должны получить следующий результат:
150
Переменные в объектах класса данных могут иметь значения по умолчанию
Вы можете назначить значения по умолчанию членам классов данных после подсказок типа. Вот пример:
from dataclasses import dataclass @dataclass class StockInHand: apples: int = 40 oranges: int = 50 mangoes: int = 60 def total_stock(self) -> int: return self.apples + self.oranges + self.mangoes stock = StockInHand() print (stock.total_stock())
Во втором последнем операторе не было предоставлено никаких аргументов во время создания нового экземпляра класса данных StockInHand, поэтому были использованы значения по умолчанию. После выполнения приведенного выше примера кода вы должны получить следующий результат:
150
Члены Dataclass изменчивы
Классы данных изменяемы, поэтому вы можете изменить значение его членов, получив на них ссылку. Ниже приведен пример кода:
from dataclasses import dataclass @dataclass class StockInHand: apples: int = 40 oranges: int = 50 mangoes: int = 60 def total_stock(self) -> int: return self.apples + self.oranges + self.mangoes stock = StockInHand() stock.apples = 100 print (stock.total_stock())
Значение переменной apples было изменено перед вызовом метода total_stock. После выполнения приведенного выше примера кода вы должны получить следующий результат:
210
Создание класса данных из списка
Вы можете создать класс данных программно, используя метод make_dataclass, как показано в примере кода ниже:
import dataclasses fields = [("apples", int, 40), ("oranges", int, 50), ("mangoes", int, 60)] StockInHand = dataclasses.make_dataclass( "StockInHand", fields, namespace={'total_stock': lambda self: self.apples + self.oranges + self.mangoes} ) stock = StockInHand() stock.apples = 100 print (stock.total_stock())
Метод make_dataclass принимает имя класса и список полей-членов в качестве двух обязательных аргументов. Вы можете определить элементы как список кортежей, где каждый кортеж содержит имя переменной, подсказку о ее типе и значение по умолчанию. Определение значения по умолчанию не требуется, вы можете опустить его, чтобы не назначать значение по умолчанию. Необязательный аргумент пространства имен принимает словарь, который можно использовать для определения функций-членов с использованием пар ключ-значение и лямбда-функций. Приведенный выше код в точности эквивалентен определению следующего класса данных вручную:
from dataclasses import dataclass @dataclass class StockInHand: apples: int = 40 oranges: int = 50 mangoes: int = 60 def total_stock(self): return self.apples + self.oranges + self.mangoes stock = StockInHand() stock.apples = 100 print (stock.total_stock())
После выполнения двух приведенных выше примеров кода вы должны получить следующий результат:
210
Зачем использовать класс данных вместо класса?
Вы можете задаться вопросом, зачем использовать классы данных, если они почти такие же, как другие классы Python? Одним из основных преимуществ использования классов данных является их краткость. Вы можете создавать классы данных, используя чистые и минимальные сокращения, без особого шаблонного кода. Они специально разработаны для использования в качестве контейнеров данных, где к переменным можно легко получить доступ с помощью точечной нотации, хотя вы также можете использовать классы данных как полноценные классы. Проще говоря, если вы хотите использовать класс Python только для того, чтобы использовать его в качестве хранилища данных, dataclass кажется лучшим выбором.
Заключение
Классы данных в Python предоставляют минимальный способ быстрого создания классов Python, предназначенных для использования в качестве хранилищ данных. Вы можете получить ссылки на члены классов данных с использованием точечной нотации, и они особенно полезны, когда вы ищете словари, такие как пары ключ-значение, к которым можно получить доступ с помощью точечной нотации.