Data classes в Python: де варто застосовувати декоратор dataclass
Python відомий тим, що це мова програмування з підтримкою об’єктно-орієнтованих парадигм, де класи є одним з основних інструментів для роботи з даними та функціоналом. Але в реальній роботі часто доводиться писати звичайний клас, завданням якого має бути лише зберігання даних, без будь-якої премудрої логіки. Щоб уникнути шаблонності в коді та скоротити випадки дублювання, у версії 3.7 мові Python з’явилася нова можливість – Data Classes.
До появи Data Classes кодерам доводилося вручну описувати прості класи Python для представлення сутностей з кількома атрибутами. Наприклад:
class Person:
def __init__(self, name: str, age: int):
self.name = name
self.age = age
def __repr__(self):
return f"Person(name={self.name}, age={self.age})"
У цьому фрагменті ми вручну створюємо конструктор і метод для рядкового представлення об’єкта. Але при додаванні нових атрибутів або методів код швидко розростається, стаючи менш зручним та підтримуваним. Data Classes автоматизують цей процес.
Щоб створити Data Class, потрібно вказати декоратор @dataclass з модуля dataclasses. Розглянемо простий приклад:
від dataclasses import dataclass @dataclass class Point: x: int y: int
У цьому фрагменті Point є класом, що містить атрибути x та y. Завдяки декоратору @dataclass, Python самостійно створює конструктор __init__(), метод __repr__() та інші корисні методи.
Тепер можна створити об’єкт цього класу:
point = Point(10, 20) print(point) # Output: Point(x=10, y=20)
Декоратор @dataclass автоматично створює метод __init__(), який ініціалізує атрибути об’єкта:
@dataclass
class Person:
name: str
age: int
p = Person("Laura", 20)
print(p) # Output: Person(name='Laura', age=20)
Data Classes самі генерують рядкове представлення для екземплярів класу, що дуже корисно при налагодженні:
print(repr(p)) # Output: Person(name='Laura', age=20)
Data Classes генерують метод __eq__(), який може порівняти об’єкти між собою виходячи з їхніх атрибутів. Ось один приклад:
p1 = Person("Laura", 20)
p2 = Person("Laura", 20)
print(p1 == p2) # Output: True
Оскільки обидва об’єкти мають однакові значення атрибутів, вони вважаються рівними.
Об’єкти, створені за допомогою Data Classes, вважаються мутабельними (змінними) за замовчанням. Але ви можете створити незмінний клас, якщо встановите параметр frozen=True. Тепер, якщо хтось спробує змінити атрибут після створення об’єкта, з’явиться помилка:
@dataclass(frozen=True) class ImmutablePoint: x: int y: int point = ImmutablePoint(1, 2) # point.x = 10 # Помилка: Cannot assign to field 'x'
Data Classes здатні автоматично створювати методи порівняння (__lt__(), __le__(), __gt__(), і __ge__()), якщо буде вказано параметр order=True:
@dataclass(order=True)
class Item:
name: str
price: float
item1 = Item("Apple", 1.0)
item2 = Item("Banana", 2.0)
print(item1 < item2) # Output: True
Використання такого параметра стане в нагоді, коли потрібно порівняти та сортувати об’єкти класу.
Data Classes підтримує кілька корисних параметрів, які можуть передаватися в декоратор @dataclass:
1. init=False: Якщо ви не хочете, щоб для якогось поля автоматично створювався конструктор, його можна вимкнути. Розглянемо наступний код:
@dataclass
class Product:
name: str
price: float = 0.0
in_stock: bool = False
discount: float = field(init=False, default=0.1)
У цьому фрагменті для атрибута конструктор автоматично не згенерується.
2. repr=False: Ця властивість виключає поле з рядкового представлення об’єкта:
@dataclass
class PrivateData:
id: int
secret: str = field (repr = False)
pd = PrivateData(1, "top_secret")
print(pd) # Output: PrivateData(id=1)
3. default_factory: Дає можливість задавати значення за замовчуванням за допомогою функції:
from typing import List
@dataclass
class DataContainer:
items: List[int] = field(default_factory=list)
container = DataContainer()
print(container.items) # Output: []
Data Classes допускає наслідування. Тому ви можете розширювати класи, додавати нові атрибути або методи. Однак, якщо ви успадкуєте від іншого класу з @dataclass, потрібно враховувати порядок ініціалізації:
@dataclass
class Employee(Person):
employee_id: int
e = Employee("Bob", 25, 1234)
print(e) # Output: Employee(name='Bob', age=25, employee_id=1234)
Тут клас Employee отримує наслідування від Person та додає нове поле employee_id.
Data Classes часто порівнюються з іншими способами роботи з даними Python, такими як іменовані кортежі (namedtuple) і словники. Розглянемо коротке порівняння:
namedtuple:
словники:
Data Classes забезпечують баланс між простотою і гнучкістю, роблячи їх кращими для структурованих даних.
Незважаючи на цілу низку очевидних переваг Data Classes у Python, можуть виникнути ситуації, коли їх використання не зовсім підходить. Ось кілька випадків, коли краще не застосовувати Data Classes:
Data Classes — це потужний спосіб роботи з класами, які використовуються для зберігання даних. Вони значно спрощують написання коду, скорочуючи число шаблонних методів, підвищуючи читаність і продуктивність. Data Classes особливо корисні, коли вам потрібні зручні та легко настроювані структури даних з підтримкою методів порівняння та відображення. З іншого боку, у них є свої обмеження: вони не підтримують складну логіку в конструкторі і високу продуктивність.
Північнокорейського самозванця, який віддалено працював системним адміністратором в американському Amazon, викрили після того, як затримка…
Вітчизняна IT-галузь демонструє ознаки повільного зростання після суттєвого падіння показників у 2022-23 роках. Наприкінці 2025…
Не минуло й двох діб після того, як GitHub оголосив про запровадження з 1 березня…
JetBrains випустила загальнодоступне останнє оновлення мови програмування Kotlin 2.3.0. Новий реліз має низку експериментальних функцій,…
Компанія OpenAI офіційно представила GPT-5.2-Codex — нову модель, яку названо «найдосконалішим інструментом для реальної розробки…
Міністерство фінансів України опублікувало законопроект про введення ПДВ для ФОП 1-3 груп. Прогнозується, що нові…