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

بايثون / الأساسيات / الدرس 4

الدوال والعقود ونطاق الأسماء

حوّل الحسابات المتكررة إلى دوال صغيرة ذات مدخلات ونتائج وحالات فشل واضحة.

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

أهداف الدرس

  • تحديد عقد مفيد
  • تصميم استدعاءات مفهومة

تحديد عقد مفيد

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

الوسائط والقيم المعادة

المعامل اسم في التعريف، والوسيطة قيمة تقدمها عند الاستدعاء. تطابق الوسائط الموضعية بحسب الترتيب، بينما توضح المسماة المعامل المقصود. تسهل القيم الافتراضية الحالات الشائعة دون إخفاء سياسة مفاجئة. يفيد المعامل الذي يلي * في فرض تسميته عند الاستدعاء، خصوصا للخيارات المنطقية المبهمة. تنهي return الاستدعاء الحالي. يعيد انتهاء الجسم دونها أو استخدامها بلا تعبير القيمة None. أما الطباعة فتعرض نصا ولا تعيد النص المعروض بوصفه نتيجة الدالة.

استقلال الحساب

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

python استقلال الحساب — مثال محلول
def total_cents(price, quantity, *, shipping=0):
    """Return the total in cents for a nonnegative order."""
    return price * quantity + shipping

print(total_cents(250, 3, shipping=100))
الناتج المتوقع
850

تكلف ثلاث قطع 750 سنتا ويضيف الشحن 100. تعيد الدالة 850 ويتولى المستدعي طباعتها.

الأسماء والوسائط القابلة للتغيير

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

python الأسماء والوسائط القابلة للتغيير — مثال محلول
def append_label(label, labels=None):
    if labels is None:
        labels = []
    labels.append(label)
    return labels

print(append_label("red"))
print(append_label("blue"))
الناتج المتوقع
['red']
['blue']

ينشأ لكل استدعاء لا يقدم labels قائمة جديدة داخل الدالة، لذلك لا تحتوي النتيجة الثانية على red.

تصميم استدعاءات مفهومة

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

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

استلام None بدلا من المجموع المعروض

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

ظهور عناصر استدعاء سابق في استدعاء لاحق

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

تغيير دالة مساعدة لقائمة المدخلات بصورة مفاجئة

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

اختبر فهمك

1. صمم دالة تحول الدقائق الصحيحة إلى زوج من الساعات والدقائق.

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

عرّف split_minutes(total) بحيث تعيد (total // 60, total % 60)، ووثق اشتراط المدخل غير السالب. يعيد split_minutes(137) الزوج (2, 17). يتيح إرجاع الزوج فصل التنسيق والتحقق من hours * 60 + minutes == total.

2. فسر الفرق بين إسناد items = [] داخل الدالة واستدعاء items.clear().

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

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

أهم ما تعلمته

  • تتيح القيم المعادة تركيب الدوال.
  • يختلف تغيير الارتباط عن تعديل الكائن.
  • الافتراضيات والآثار الجانبية جزء من عقد الدالة.

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