Dataclass در پایتون چیست؟
آموزش ساخت کلاسهای تمیز و حرفهای با
@dataclass
Dataclass چیست؟
در پایتون از کلاسها برای ساخت اشیایی استفاده میکنیم که میتوانند داده و رفتار داشته باشند.
اما گاهی یک کلاس فقط برای نگهداری اطلاعات استفاده میشود و بخش زیادی از کد آن مربوط به تعریف اولیه، نمایش شیء، مقایسه اشیا و مدیریت مقادیر پیشفرض است.
Dataclass قابلیتی در پایتون است که ایجاد چنین کلاسهایی را سادهتر میکند.
با استفاده از دکوراتور @dataclass
پایتون میتواند بعضی از متدهای رایج کلاس را بهصورت
خودکار ایجاد کند.
مشکل کلاس معمولی چیست؟
فرض کنید میخواهیم اطلاعات یک کاربر را نگهداری کنیم.
در یک کلاس معمولی ممکن است کدی شبیه این بنویسیم:
class User:
def __init__(self, name, age):
self.name = name
self.age = age
user = User("Ali", 25)
print(user.name)
print(user.age)
این کد کاملاً درست است، اما برای کلاسهایی که عمدتاً وظیفه نگهداری داده دارند، میتوان آن را سادهتر کرد.
ساخت اولین Dataclass
برای استفاده از Dataclass ابتدا باید آن را از
ماژول dataclasses وارد کنیم.
from dataclasses import dataclass
@dataclass
class User:
name: str
age: int
حالا میتوانیم یک شیء از این کلاس ایجاد کنیم:
user = User("Ali", 25)
print(user)
خروجی میتواند به شکل زیر باشد:
User(name='Ali', age=25)
Dataclass بسیاری از کارهای تکراری را برای ما انجام میدهد.
Dataclass و __init__
یکی از مزایای مهم Dataclass این است که بر اساس فیلدهای
تعریفشده میتواند متد __init__ را بهصورت
خودکار ایجاد کند.
from dataclasses import dataclass
@dataclass
class Product:
name: str
price: float
quantity: int
product = Product(
"Laptop",
1200.0,
2
)
بنابراین لازم نیست برای این فیلدها بهصورت دستی
__init__ بنویسیم.
Dataclass و Type Hints
Dataclass معمولاً همراه با Type Hint استفاده میشود.
@dataclass
class Student:
name: str
age: int
grade: float
Type Hint مشخص میکند هر فیلد چه نوع دادهای را انتظار دارد و ساختار کلاس را خواناتر میکند.
برای آشنایی بیشتر با Type Hints میتوانید درس قبلی را نیز مطالعه کنید.
مقدار پیشفرض در Dataclass
میتوان برای فیلدها مقدار پیشفرض تعیین کرد.
from dataclasses import dataclass
@dataclass
class User:
name: str
age: int = 18
user = User("Ali")
print(user)
چون برای age مقدار پیشفرض
18 تعیین شده است، هنگام ساخت شیء
لازم نیست مقدار آن را وارد کنیم.
تابع field در Dataclass
برای کنترل دقیقتر فیلدها میتوان از
field() استفاده کرد.
from dataclasses import dataclass, field
@dataclass
class Product:
name: str
price: float = field(default=0.0)
field() امکانات بیشتری برای تعریف
ویژگیهای فیلد در اختیار ما قرار میدهد.
default_factory چیست؟
زمانی که میخواهیم مقدار پیشفرضی مثل یک لیست یا دیکشنری
برای هر شیء بهصورت جداگانه ساخته شود، میتوانیم از
default_factory استفاده کنیم.
from dataclasses import dataclass, field
@dataclass
class User:
name: str
skills: list[str] = field(
default_factory=list
)
در این حالت هر شیء یک لیست مستقل برای
skills خواهد داشت.
این روش از استفاده اشتباه از یک لیست مشترک جلوگیری میکند.
Dataclass و __repr__
Dataclass بهصورت پیشفرض یک نمایش متنی مناسب برای اشیا ایجاد میکند.
@dataclass
class User:
name: str
age: int
user = User("Sara", 22)
print(user)
خروجی:
User(name='Sara', age=22)
این ویژگی برای Debug کردن و بررسی اطلاعات اشیا بسیار مفید است.
مقایسه اشیا در Dataclass
Dataclass میتواند امکان مقایسه بر اساس فیلدهای کلاس را نیز فراهم کند.
from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int
p1 = Point(10, 20)
p2 = Point(10, 20)
print(p1 == p2)
خروجی:
True
زیرا مقادیر فیلدهای دو شیء با یکدیگر برابر هستند.
frozen=True چیست؟
اگر بخواهیم پس از ایجاد شیء، مقادیر فیلدهای آن
قابل تغییر نباشند، میتوانیم از
frozen=True استفاده کنیم.
from dataclasses import dataclass
@dataclass(frozen=True)
class Point:
x: int
y: int
point = Point(10, 20)
حالا تلاش برای تغییر یکی از فیلدها با محدودیت مواجه خواهد شد.
point.x = 50
بنابراین frozen=True برای ساخت اشیایی
که نباید پس از ایجاد تغییر کنند، کاربرد دارد.
تبدیل Dataclass به Dictionary با asdict
تابع asdict() میتواند یک شیء Dataclass
را به Dictionary تبدیل کند.
from dataclasses import dataclass, asdict
@dataclass
class User:
name: str
age: int
user = User("Ali", 25)
data = asdict(user)
print(data)
خروجی:
{
'name': 'Ali',
'age': 25
}
این قابلیت هنگام تبدیل دادهها برای ذخیرهسازی یا ارسال اطلاعات بسیار کاربردی است.
Dataclass تو در تو
یک Dataclass میتواند شامل شیء دیگری از نوع Dataclass باشد.
from dataclasses import dataclass
@dataclass
class Address:
city: str
country: str
@dataclass
class User:
name: str
address: Address
address = Address(
"Tehran",
"Iran"
)
user = User(
"Ali",
address
)
print(user)
این روش برای مدلسازی دادههای پیچیدهتر بسیار مفید است.
آیا Dataclass میتواند متد داشته باشد؟
بله. Dataclass فقط برای نگهداری داده نیست و میتوانیم داخل آن متد نیز تعریف کنیم.
from dataclasses import dataclass
@dataclass
class Product:
name: str
price: float
quantity: int
def total_price(self) -> float:
return self.price * self.quantity
product = Product(
"Mouse",
20.0,
3
)
print(product.total_price())
بنابراین Dataclass میتواند هم داده و هم رفتار را در خود داشته باشد.
مثال واقعی: مدیریت اطلاعات کاربران
فرض کنید میخواهیم اطلاعات کاربران یک برنامه را به شکل مرتب نگهداری کنیم.
from dataclasses import dataclass, field
@dataclass
class User:
username: str
age: int
email: str
skills: list[str] = field(
default_factory=list
)
def add_skill(self, skill: str) -> None:
self.skills.append(skill)
user = User(
"ali_python",
25,
"ali@example.com"
)
user.add_skill("Python")
user.add_skill("Django")
print(user)
در این مثال اطلاعات کاربر، لیست مهارتها و متدی برای اضافه کردن مهارت در یک ساختار مشخص قرار گرفتهاند.
تفاوت Dataclass و Class معمولی
Dataclass در واقع نوع متفاوتی از کلاس نیست؛ بلکه ابزاری است که ساخت کلاسهای دادهمحور را سادهتر میکند.
اگر کلاس شما منطق و رفتار پیچیدهای دارد، کلاس معمولی همچنان گزینه مناسبی است.
اما اگر هدف اصلی کلاس نگهداری دادههاست، Dataclass میتواند مقدار زیادی از کدهای تکراری را حذف کند.
کاربردهای Dataclass
- مدلسازی اطلاعات کاربران
- ساخت مدلهای داده
- مدیریت محصولات و سفارشها
- ذخیره تنظیمات برنامه
- ساخت ساختارهای داده خوانا
- مدیریت دادههای API
- پروژههای وب و Backend
- پروژههای هوش مصنوعی و پردازش داده
اشتباهات رایج در Dataclass
۱. استفاده اشتباه از لیست پیشفرض
برای فیلدهایی مانند لیست و دیکشنری بهتر است از
default_factory استفاده کنیم.
۲. استفاده از Dataclass برای هر کلاس
Dataclass برای همه کلاسها ضروری نیست. اگر کلاس منطق پیچیدهای دارد، یک کلاس معمولی ممکن است مناسبتر باشد.
۳. فراموش کردن Type Hint
Dataclass معمولاً با Type Hint استفاده میشود و نوشتن نوع فیلدها باعث خوانایی بهتر ساختار داده میشود.
جمعبندی Dataclass در پایتون
Dataclass یکی از ابزارهای مفید پایتون برای ساخت کلاسهایی است که تمرکز اصلی آنها روی نگهداری داده است.
با استفاده از @dataclass بسیاری از کدهای
تکراری مانند __init__ و نمایش مناسب شیء
بهصورت خودکار مدیریت میشوند.
ابزارهایی مانند field()،
default_factory،
frozen=True و asdict()
نیز امکانات بیشتری در اختیار ما قرار میدهند.
ترکیب Dataclass با Type Hints میتواند ساختار دادههای پروژههای پایتون را بسیار خواناتر و منظمتر کند.
تمرینهای Dataclass
-
یک Dataclass به نام
Studentبسازید که نام، سن و معدل دانشآموز را نگهداری کند. - برای یکی از فیلدها مقدار پیشفرض تعیین کنید.
-
یک فیلد لیستی با
default_factoryایجاد کنید. - یک متد برای Dataclass بنویسید که اطلاعات شیء را به شکل مناسب نمایش دهد.
- یک Dataclass برای محصول بسازید که قیمت و تعداد را دریافت کند و قیمت کل را محاسبه کند.
-
یک Dataclass با
frozen=Trueبسازید و تفاوت آن را با Dataclass معمولی بررسی کنید.
سوالات متداول درباره Dataclass
Dataclass در پایتون چیست؟
Dataclass ابزاری برای ساخت سادهتر کلاسهایی است که عمدتاً برای نگهداری داده استفاده میشوند.
@dataclass چه کاری انجام میدهد؟
این دکوراتور به پایتون اجازه میدهد بعضی از متدهای رایج کلاس را بر اساس فیلدهای تعریفشده بهصورت خودکار ایجاد کند.
آیا Dataclass جایگزین کلاس معمولی است؟
خیر. Dataclass یک ابزار برای سادهتر کردن برخی کلاسهاست. کلاسهای معمولی همچنان برای بسیاری از کاربردها مناسب هستند.
default_factory چه کاربردی دارد؟
برای ایجاد مقدار پیشفرض جدید برای هر شیء استفاده میشود؛ مخصوصاً برای ساخت فیلدهایی مانند لیست و دیکشنری.
frozen=True چه کاری انجام میدهد؟
باعث میشود فیلدهای Dataclass پس از ایجاد شیء به شکل معمول قابل تغییر نباشند.
asdict() چیست؟
asdict() یک شیء Dataclass را به ساختار
Dictionary تبدیل میکند.