بايثون Dataclass: شرح شامل وأمثلة عملية لتحسين إدارة البيانات

1. ما هو الـ Dataclass؟

نظرة عامة على الـ Dataclass

يعد dataclass في بايثون ميزة تم تقديمها في الإصدار 3.7، وتُستخدم لتبسيط تعريف الفئات وتقليل الكود المتكرر. وهي مفيدة بشكل خاص عند تعريف فئات لحفظ البيانات بكفاءة. باستخدام dataclass، يمكن توليد دوال مثل __init__ و__repr__ تلقائيًا داخل الفئة.

على سبيل المثال، في تعريف الفئات التقليدي كان يجب عليك كتابة دالة التهيئة يدويًا، بينما مع dataclass يمكنك جعل التعريف مختصرًا كما يلي:

from dataclasses import dataclass

@dataclass
class User:
    name: str
    age: int

الكود أعلاه يولّد تلقائيًا دوال __init__ و__repr__، مما يجعل من السهل تعريف فئات لحفظ البيانات. بالإضافة إلى ذلك، يوضح استخدام التوضيح النوعي (type annotation) أنواع البيانات وبنية الفئة، مما يُحسن من وضوح الكود.

2. مزايا الـ Dataclass

تبسيط الكود

باستخدام dataclass، يصبح الكود أقصر وأكثر وضوحًا مقارنة بتعريف الفئات التقليدي. حيث يتم توليد دوال __init__ و__repr__ تلقائيًا، فلا حاجة لكتابتها يدويًا، مما يقلل من الأخطاء البرمجية.

@dataclass
class Product:
    id: int
    name: str
    price: float

حتى في الفئات البسيطة كهذه، يوفر dataclass جميع الوظائف مثل التهيئة والتمثيل النصي تلقائيًا. كما أن إضافة أو تعديل الحقول أمر سهل ومرن.

الدوال المُولدة تلقائيًا

بالإضافة إلى __init__، يقوم dataclass بتوليد دوال مثل __repr__ و__eq__ تلقائيًا. وهذا يُسهل مقارنة الكائنات وتحويلها إلى تمثيل نصي دون الحاجة لكتابة كود إضافي.

القيم الافتراضية وتوضيح الأنواع

يدعم dataclass تعيين قيم افتراضية للحقول، وكذلك توضيح الأنواع. مما يمكّن المطور من تحديد نوع البيانات والقيم الأولية بشكل واضح وسهل.

@dataclass
class Employee:
    name: str
    age: int = 25  # القيمة الافتراضية 25 سنة

يمكنك تعيين القيم الافتراضية كما تحتاج، مما يسمح بأن تكون بعض المعاملات اختيارية عند تهيئة الكائن.

侍エンジニア塾

3. مقارنة مع تعريف الفئات التقليدي

تحسين الذاكرة والأداء

يتميز dataclass عن الفئات التقليدية بكفاءة أكبر في استخدام الذاكرة والأداء. عند التعامل مع كميات كبيرة من البيانات، يمكن الاستفادة من خيار slots الذي أُضيف في بايثون 3.10 لتحسين إدارة الذاكرة.

@dataclass(slots=True)
class User:
    name: str
    age: int

باستخدام slots=True، يتم استخدام بنية ذاكرة أخف لكل كائن، بدلاً من القاموس الافتراضي، مما يقلل من استهلاك الذاكرة ويزيد من سرعة الوصول للخصائص.

الاختلاف عن الفئات التقليدية

في الفئات التقليدية، كان عليك كتابة كل دالة يدوياً، بينما مع dataclass كل ذلك يتم تلقائياً، ما يتيح التركيز على تصميم الهيكل البياني. حتى مع وجود العديد من الحقول أو الحاجة لسلوكيات مخصصة، يظل الكود بسيطًا وسهل الصيانة.

4. الميزات المتقدمة للـ Dataclass

تحسين الذاكرة باستخدام slots

ابتداءً من بايثون 3.10، يدعم dataclass خيار slots الذي يسمح بتخزين خصائص الكائن بطريقة أكثر فعالية من حيث الذاكرة، باستخدام ما يُسمى “slots” بدلاً من القاموس.

مثال عملي:

@dataclass(slots=True)
class Person:
    name: str
    age: int

عند استخدام هذا مع بيانات ضخمة، ستلاحظ انخفاضًا كبيرًا في استهلاك الذاكرة. كما يمنع slots إضافة خصائص جديدة للكائنات بشكل ديناميكي، مما يساعد في تجنب بعض الأخطاء.

إنشاء فئات ثابتة (غير قابلة للتغيير) (frozen=True)

تدعم dataclass الخيار frozen=True، والذي يُنتج فئات غير قابلة للتغيير بعد الإنشاء. هذا مفيد عندما تحتاج لضمان ثبات البيانات، أو في التطبيقات متعددة الخيوط.

@dataclass(frozen=True)
class ImmutableUser:
    username: str
    age: int

عند محاولة تعديل خاصية لأي كائن تم إنشاؤه باستخدام frozen=True ستظهر رسالة خطأ AttributeError.

الحقول المخصصة ودالة field()

يمكنك التحكم في سلوك الحقول باستخدام دالة field()، مثل تجاهل بعض الحقول عند التهيئة أو تحديد قيم افتراضية معقدة.

@dataclass
class Product:
    name: str
    price: float = field(default=0.0, init=False)

في هذا المثال، الحقل price ليس مطلوبًا عند التهيئة ويأخذ القيمة 0.0 افتراضيًا.

5. أمثلة عملية على استخدام الـ Dataclass

إدارة بيانات المستخدمين

يُعد dataclass مناسبًا جدًا للفئات التي الغرض منها حفظ البيانات، مثل بيانات المستخدمين أو الإعدادات.

@dataclass
class UserProfile:
    username: str
    email: str
    is_active: bool = True

حتى مع وجود العديد من الحقول، يظل الكود واضحًا وسهل الصيانة عند استخدام dataclass.

تحويل البيانات والتعامل مع JSON

dataclass مفيد جدًا في تحويل البيانات أو التعامل مع JSON. يمكنك بسهولة تحويل بيانات من قاعدة بيانات أو API إلى كائنات فئة، وتحويلها إلى صيغ أخرى. كما يوفر مكتبة dataclasses في بايثون دوال لتحويل الكائنات إلى قواميس أو tuples.

import json
from dataclasses import dataclass, asdict

@dataclass
class Product:
    id: int
    name: str
    price: float

product = Product(1, "Laptop", 999.99)
print(json.dumps(asdict(product)))

في المثال أعلاه، تُحوّل الكائنات باستخدام asdict() إلى قاموس، ثم إلى صيغة JSON. هذا يجعل التعامل مع البيانات وتحويلها بين الصيغ أمرًا بسيطًا وفعالاً.

6. التكامل مع مكتبات أخرى

التحقق من صحة البيانات باستخدام Pydantic

يمكن دمج dataclass مع مكتبات بايثون أخرى، وأبرزها Pydantic للتحقق من صحة البيانات. يتيح Pydantic إضافة منطق تحقق بسهولة استنادًا إلى توضيحات الأنواع.
مثال:

from pydantic.dataclasses import dataclass
from pydantic import ValidationError

@dataclass
class Book:
    title: str
    pages: int

try:
    book = Book(title=123, pages="two hundred")
except ValidationError as e:
    print(e)

سيؤدي إدخال نوع غير صحيح في title أو pages إلى ظهور خطأ تحقق تلقائيًا. هذا مفيد بشكل خاص في التطبيقات الضخمة وواجهات برمجة التطبيقات.

7. أخطاء شائعة عند استخدام الـ Dataclass

المعاملات الافتراضية القابلة للتغيير

أحد الأخطاء الشائعة هو تعيين كائنات قابلة للتغيير مثل القوائم أو القواميس كقيمة افتراضية لمعامل ما. يؤدي ذلك إلى مشاركة نفس الكائن بين جميع الحالات.

from dataclasses import dataclass, field

@dataclass
class Team:
    members: list = field(default_factory=list)

من الأفضل استخدام default_factory لإنشاء كائن جديد لكل حالة، لتفادي الأخطاء غير المتوقعة.

عدم توافق نوع الخاصية مع القيمة الافتراضية

خطأ آخر شائع هو عدم التوافق بين نوع الخاصية والقيمة الافتراضية. يجب التأكد من أن القيمة الافتراضية تتوافق مع نوع الخاصية كما هو موضح في توضيحات الأنواع.

@dataclass
class User:
    name: str
    age: int = "twenty"  # هذا غير صحيح

يجب دائمًا تعيين القيم الافتراضية بشكل يتوافق مع النوع المحدد لتفادي الأخطاء.

8. الخلاصة

تُبسّط dataclass في بايثون تعريف الفئات الخاصة بحفظ البيانات وتوفر الكثير من الميزات العملية. فهي تحسن وضوح الكود، وتدعم خيارات متقدمة مثل slots لتحسين الذاكرة وfrozen للثبات، كما يمكن دمجها بسهولة مع مكتبات التحقق من صحة البيانات أو التعامل مع JSON، مما يجعلها أداة قوية في تطوير التطبيقات الحديثة.

استفد من هذه المزايا وجرب استخدام dataclass في مشروعك القادم!

RUNTEQ(ランテック)|超実戦型エンジニア育成スクール