محتويات الدورة

بايثون / برامج موثوقة / الدرس 11

الأصناف وأصناف البيانات والملكية

نمذج الحالة ذات المعنى بثوابت صريحة، وفضل التركيب، وافهم حدود السلوك الذي تولده أصناف البيانات.

وقت القراءة التقريبي: 4 دقيقةتاريخ مراجعة المحتوى
في هذه الصفحة

أهداف الدرس

  • الكائن يجمع الحالة والسلوك
  • نماذج القيم والتطور

الكائن يجمع الحالة والسلوك

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

الثوابت والتركيب

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

التحقق قبل تغيير الحالة

يحفظ المثال الرصيد بسنتات صحيحة. تقبل deposit مقدارا غير سالب وتتحقق منه قبل التعديل. تقرأ النتيجة عبر خاصية وتتبع السمة الداخلية اتفاق الشرطة السفلية. هذا عرض تعليمي لا نظام مصرفي؛ فلا يشمل التخزين أو التفويض أو التزامن أو كل تحقق نوعي. قيمته في إعطاء الثابت موضعا واضحا. اختبر العملية المرفوضة بنوع الاستثناء وبقاء الرصيد، وإلا قد يرفع التنفيذ الخطأ بعد إفساد الحالة.

python التحقق قبل تغيير الحالة — مثال محلول
class Balance:
    def __init__(self):
        self._cents = 0
    def deposit(self, amount):
        if amount < 0:
            raise ValueError("amount must be nonnegative")
        self._cents += amount
    @property
    def cents(self):
        return self._cents

balance = Balance()
balance.deposit(250)
print(balance.cents)
الناتج المتوقع
250

يسبق التحقق التعديل، وتعرض الخاصية الرصيد. يستخدم المثال مقدارا صحيحا صالحا ثابتا.

تقليل الشفرة المتكررة بأصناف البيانات

تولد dataclass التهيئة والتمثيل والمساواة من الحقول المعلّمة، لكنها لا تفرض أنواعها أثناء التشغيل. استخدم field(default_factory=list) لقائمة جديدة لكل نسخة. تمنع frozen=True إعادة ربط الحقول بالطريقة المعتادة، لكنها لا تجعل قائمة داخلية ثابتة. تقارن المساواة المولدة الحقول وفق قواعد أصناف البيانات، فحدد معناها عندما تمثل الكائنات هويات لا قيما متبادلة. ينمذج المثال شحنتين بقائمتين مستقلتين، ويشرح الملكية دون افتراض أن الاختصار يضمن صحة المجال.

python تقليل الشفرة المتكررة بأصناف البيانات — مثال محلول
from dataclasses import dataclass, field

@dataclass
class Shipment:
    code: str
    labels: list[str] = field(default_factory=list)

first = Shipment("A")
second = Shipment("B")
first.labels.append("fragile")
print(first.labels)
print(second.labels)
الناتج المتوقع
['fragile']
[]

تستدعى دالة المصنع لكل نسخة، فلا تضيف عملية تعديل قائمة الشحنة الأولى عنصرا إلى الثانية.

نماذج القيم والتطور

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

الأخطاء الشائعة وإصلاحها

اشتراك النسخ كلها في قائمة واحدة

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

السماح بتغيير قائمة داخلية رغم frozen=True

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

تغيير الرصيد رغم رفض العملية

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

اختبر فهمك

1. صمم قيمة نقطة ثابتة بحقلين صحيحين x وy. ماذا تضمن العلامات النوعية؟

اعرض الحل المشروح

استخدم @dataclass(frozen=True) مع x: int وy: int. تفيد المساواة والتمثيل المولدان، وترفض إعادة الإسناد العادية. ترشد العلامات الأدوات لكنها لا ترفض نصا وقت التشغيل؛ تحقق عند الحدود إذا كان النوع الصحيح إلزاميا.

2. ماذا يفحص الاختبار بعد سحب مرفوض؟

اعرض الحل المشروح

افحص الاستثناء الموثق وقارن الرصيد بقيمته السابقة الدقيقة، ثم اختبر سحبا صالحا منفصلا. يتضمن عقد الفشل حفظ الحالة؛ وقد يخفي فحص الاستثناء وحده تعديلا جزئيا سبق رفعه.

أهم ما تعلمته

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

المراجع الرسمية