آموزش پایتون - دیتاکلاس
ویژگی dataclass یکی از قابلیتهای پایتون است که به افزودن خودکار متدهای ویژه به کلاسهای تعریفشده توسط کاربر کمک میکند. به عنوان مثال، یک dataclass میتواند برای تولید خودکار متد سازنده (constructor) برای کلاس شما استفاده شود تا بتوانید به راحتی نمونههایی از کلاس بسازید. در این فصل، تمام ویژگیهای ماژول dataclass را با کمک مثالها توضیح خواهیم داد.
دیتاکلاس (Dataclass) چیست؟
یک dataclass در واقع یک کلاس پایتون است که با دکوراتور dataclass@ از ماژول dataclasses مشخص میشود. از آن برای تولید خودکار متدهای ویژه مانند متد سازنده ()init__repr__، متد نمایش رشتهای ()__repr__، متد برابری ()eq__ و موارد دیگر بر اساس ویژگیهای کلاس (class attributes) تعریفشده در بدنه کلاس استفاده میشود. این به زبان ساده یعنی استفاده از dataclassها میتواند کدهای تکراری (boilerplate) را در تعریف کلاسهای شما کاهش دهد.
سنتکس Dataclass
سنتکس تعریف یک dataclass به صورت زیر است −
@dataclass(init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False)
هر آرگومان یک مقدار بولین (boolean) میگیرد که مشخص میکند آیا متدهای ویژه مربوطه باید به طور خودکار تولید شوند یا خیر.
دکوراتور dataclass@ میتواند این گزینهها را دریافت کند:
- init (پیشفرض: True) − به طور خودکار یک متد ()init__ برای مقداردهی اولیه نمونههای کلاس ایجاد میکند.
- repr (پیشفرض: True) − به طور خودکار یک متد ()repr__ برای ارائه یک نمایش رشتهای خوانا از شئ ایجاد میکند.
- eq (پیشفرض: True) − یک متد ()eq__ برای مقایسه اشیاء با استفاده از عملگر == تولید میکند.
- order (پیشفرض: False) − اگر روی True تنظیم شود، متدهای مقایسه (مانند < و >) برای مرتبسازی اشیاء تولید میشوند.
- unsafe_hash (پیشفرض: False) − اگر false باشد، یک متد ()hash__ پیشفرض بر اساس نحوه تعریف برابری و تغییرپذیری ایجاد میکند.
- frozen (پیشفرض: False) − نمونههای تغییرناپذیر (immutable) ایجاد میکند (پس از ایجاد قابل تغییر نیستند).
ایجاد یک Dataclass
در کد زیر میتوانید ببینید که ما یک dataclass ساده به نام Student با سه ویژگی تعریف کردهایم: name، age و percent. اگرچه ما از سازنده یا سایر متدهای ویژه استفاده نمیکنیم، اما همچنان میتوانیم نمونههایی از کلاس Student ایجاد کرده و از ویژگیهای آن استفاده کنیم. این به این دلیل است که دکوراتور dataclass به طور خودکار این متدها را برای ما تولید میکند.
from dataclasses import dataclass
@dataclass
class Student:
name: str
age: int
percent: float
s1 = Student("Alice", 20, 90.0)
s2 = Student("Bob", 22, 85.5)
print(s1)
print(s1 == s2)
خروجی کد بالا به صورت زیر خواهد بود −
Student(name='Alice', age=20, percent=90.0)
False
مثال بدون استفاده از Dataclass
کد بالا معادل کد زیر در تعریف کلاس سنتی بدون استفاده از dataclass است −
class Student:
def __init__(self, name: str, age: int, percent: float):
self.name = name
self.age = age
self.percent = percent
def __repr__(self):
return f"Student(name={self.name}, age={self.age}, percent={self.percent})"
def __eq__(self, other):
if not isinstance(other, Student):
return NotImplemented
return (self.name == other.name and self.age == other.age and self.percent == other.percent)
s1 = Student("Alice", 20, 90.0)
s2 = Student("Bob", 22, 85.5)
print(s1)
print(s1 == s2)
خروجی این کد مشابه کد بالا خواهد بود −
Student(name='Alice', age=20, percent=90.0)
False
مقادیر پیشفرض در Dataclass
شما همچنین میتوانید مقادیر پیشفرض برای ویژگیها در یک dataclass ارائه دهید. اگر در هنگام ایجاد یک نمونه مقداری ارائه نشود، از مقدار پیشفرض استفاده خواهد شد. در کد زیر، ما مقدار پیشفرض 0.0 را برای ویژگی percent قرار دادهایم.
from dataclasses import dataclass
@dataclass
class Student:
name: str
age: int
percent: float = 0.0 # Default value for percent
s1 = Student("Alice", 20)
s2 = Student("Bob", 22, 85.5)
print(s1)
print(s2)
خروجی کد بالا به صورت زیر خواهد بود −
Student(name='Alice', age=20, percent=0.0)
Student(name='Bob', age=22, percent=85.5)
Dataclass با مقادیر پیشفرض تغییرپذیر (Mutable)
مقادیر پیشفرض تغییرپذیر به مقادیر پیشفرضی اشاره دارند که میتوانند پس از ایجاد نمونه تغییر کنند، مانند لیستها یا دیکشنریها. هنگام استفاده از مقادیر پیشفرض تغییرپذیر در یک dataclass، توصیه میشود از تابع ()field از ماژول dataclasses با پارامتر default_factory استفاده کنید. زیرا اگر مستقیماً از یک شئ تغییرپذیر به عنوان مقدار پیشفرض استفاده کنید، بین تمام نمونههای dataclass به اشتراک گذاشته خواهد شد. این امر میتواند منجر به مشکلات امنیتی و رفتارهای غیرمنتظره شود.
در کد زیر، ما یک dataclass به نام Course با یک مقدار پیشفرض تغییرپذیر برای ویژگی students تعریف کردهایم.
from dataclasses import dataclass, field
from typing import List
@dataclass
class Course:
name: str
students: List[str] = field(default_factory=list) # Mutable default value
course1 = Course("Math")
course2 = Course("Science", ["Alice", "Bob"])
course1.students.append("Charlie")
print(course1)
print(course2)
خروجی کد بالا به صورت زیر خواهد بود −
Course(name='Math', students=['Charlie'])
Course(name='Science', students=['Alice', 'Bob'])
پیشرفت مطالعه: وضعیت خواندهشدن این درس فقط در همین مرورگر ذخیره میشود؛ بدون نیاز به حساب کاربری.