1.4 · الدوال والوسائط والنطاق

المستوى 1 · أساسيات اللغة

1.4الدوال والوسائط والنطاق

الهدف: تعريف الدوال بـ def، وتناول الوسائط والقيم الافتراضية و*args/**kwargs وreturn ونطاق المتغيرات.
الوقت المقدّر: 14 دقيقة · قراءة ذاتية · إذا كان لديك 5 دقائق فقط: اقرأ «الأساسي في 30 ثانية» + المخطط.

الأساسي في 30 ثانية

  • الدالة = عمل واحد واسم فعل : def calculer_tva(prix_ht): + return — فالعرض (print) ليس ردّا.
  • افتراضيات غير قابلة للتعديل : def f(items=None) ثم الإنشاء في الداخل — وليس def f(items=[]) التي تبقى بين الاستدعاءات.
  • محلي أولا وعمومي أبدا : المعطيات في الوسائط، والنتيجة عبر return — و*args/**kwargs للمرونة.

حالة مستمرة — نبيل يوحّد حساباته في الجزائر

يحسب نبيل متوسط الدرجات في أربعة مواضع من سكربته بالنسخ واللصق نفسه — وحين تغيّرت القاعدة (تجاهل الأصفار) نسي موضعين : فصار تقرير من أربعة خاطئا. فأنشأ دالة moyenne(*notes) تستقبل كل شيء في الوسائط وتردّ النتيجة : فصار موضع واحد للتصحيح. وفي الطريق، صحح def ajouter(x, items=[]) التي كانت تتراكم بين الاستدعاءات (None + إنشاء في الداخل) واستبدل print بـ return. فعادت التقارير الأربعة صحيحة دفعة واحدة.

تتمة الحالة 1.1-1.3 — ينتقل نبيل من التكرار إلى إعادة الاستعمال.

1. الدالة = عمل واحد واسم فعل

الدالة (function) كتلة مسماة قابلة لإعادة الاستعمال : def calculer_tva(prix_ht): — اسم فعل + snake_case ومسؤولية واحدة، وتردّ النتيجة بـ return. ودون return تردّ الدالة None : فـ print تعرض وreturn تنقل — ولا يعوّض print عن return. وهو مبدأ DRY (لا تكرر نفسك).

يستبدل نبيل نسخه الأربع الملصقة للمتوسط بـ moyenne(*notes) : فموضع واحد للتصحيح حين تتغير القاعدة، وأربعة تقارير صحيحة.

2. الوسائط والافتراضيات والنطاق

الوسائط (parameters) معلنة في التعريف، والحجج (arguments) ممررة عند الاستدعاء ؛ وتأتي الافتراضيات بعد الإلزامية (def saluer(nom, politesse="مرحبا")). والفخ الشهير : def f(items=[]) — فالقائمة تبقى بين الاستدعاءات، فاكتب def f(items=None). يجمع *args قيما، ويجمع **kwargs أزواج اسم=قيمة. والنطاق (scope) : فالمتغير المنشأ في الدالة محلي (NameError في الخارج) — فمرر بالوسائط، واستعد بـ return.

يصحح نبيل افتراضيه القابل للتعديل إلى None، ويضيف moyenne(*notes) لدرجتين ثم 5 درجات، ويلاحظ NameError لمتغير محلي طُلب في الخارج : فالمحلي مقابل العمومي محسوم.

خطأ شائع في الفهم: « تكفي print في الدالة » أو « افتراضي [] عملي ». لا. فـ print تعرض على الشاشة لكنها لا تنقل شيئا : فدون return يساوي الاستدعاء None ولا تُخزن النتيجة ولا تُحسب. والافتراضي القابل للتعديل يُنشأ مرة واحدة : فـ def f(items=[]) تتراكم بين الاستدعاءات — فـ None + إنشاء في الداخل، دائما.
دوال سليمة عمل واحد وافتراضيات آمنة ونطاق محلي عمل واحد (فعل) def +return وليس printالافتراضيات (غير قابلة للتعديل) Noneوليس [] ؛ و*args/**kwargsالنطاق (المحلي) الوسائطمدخلا وreturn مخرجا
عمل واحد وافتراضيات آمنة ونطاق محلي
نص المخطط (SEO / قارئات الشاشة / الترجمة): 1) عرّف : يكتب نبيل def moyenne(*notes) مرة واحدة بدلا من أربع نسخ ملصقة — اسم فعل ومسؤولية واحدة وreturn. 2) أمّن : افتراضيات غير قابلة للتعديل (None + إنشاء في الداخل)، و*args للعدد المتغير، و**kwargs للخيارات. 3) اعزل : متغيرات محلية، وكل شيء يدخل بالوسائط، وكل شيء يخرج بـ return — دون عمومية. الدرس : الدالة = واجهة صريحة وفضاء معزول ونتيجة مردودة.

🔎 مثال ملموس — 🔎 مثال ملموس — فخ القائمة الافتراضية

الخلل الشهير، كما واجهه نبيل في متوسطاته.

def ajouter(x, items=None):
    items = items if items is not None else []
    items.append(x)
    return items
print(ajouter(1))  # [1]
print(ajouter(2))  # [2] : دون مفاجأة
def moyenne(*notes):
    return sum(notes) / len(notes)
print(moyenne(12, 15, 9))

القراءة : الافتراضي القابل للتعديل يُنشأ مرة واحدة — وNone + إنشاء في الداخل يتفاداه.

الدرس : يجمع *args عددا متغيرا من الحجج ؛ ويجعل return النتيجة قابلة لإعادة الاستعمال.

مفردات القسم

الدالة / def
كتلة شيفرة مسماة قابلة لإعادة الاستعمال، تُعرَّف بـ def nom(parameters):. وتُستدعى بـ nom(arguments). اسم فعل ومسؤولية واحدة (DRY).

مثال بسيط: moyenne(*notes) الوحيدة لنبيل، المستدعاة أربع مرات.

ما ليس كذلك: الحساب نفسه منسوخا ملصقا في أربعة مواضع.

رد فعل: حساب تكرر مرتين = دالة.

الوسيط / الحجة
الوسيط هو المتغير المعلن في التعريف ؛ والحجة هي القيمة الحقيقية الممررة عند الاستدعاء. وتأتي الافتراضيات بعد الإلزامية.

مثال بسيط: politesse="مرحبا" في saluer(nom) عند نبيل.

ما ليس كذلك: افتراضي قابل للتعديل [] مشترك بين الاستدعاءات.

رد فعل: افتراضيات غير قابلة للتعديل (None)، وليس [] أو {} أبدا.

return
تردّ قيمة مخرجا للدالة وتنهي تنفيذها. ودون return تردّ الدالة None. فـ print تعرض وreturn تنقل.

مثال بسيط: المتوسط الذي ردّه نبيل، ثم خُزّن وعُرض.

ما ليس كذلك: دالة تعرض بـ print دون return، غير صالحة لحساب.

رد فعل: نتيجة تُعاد استعمالها = return دائما.

النطاق (scope)
منطقة رؤية المتغير. فالمتغير المنشأ في دالة محلي : لا يوجد في الخارج (NameError).

مثال بسيط: المتغير المحلي لنبيل، غير المتاح في الخارج.

ما ليس كذلك: تعديل عمومية بـ global بدلا من وسيط.

رد فعل: تحتاج معلومة ؟ وسيط ؛ وتحتاج النتيجة ؟ return.

*args / **kwargs
يتيحان استقبال عدد متغير من الحجج : *args (صف قيم)، و**kwargs (قاموس أزواج اسم=قيمة).

مثال بسيط: moyenne(*notes) لنبيل بدرجتين ثم 5 درجات.

ما ليس كذلك: خمسة وسائط اختيارية مطولة بدلا من *args.

رد فعل: عدد مجهول = *args ؛ وخيارات مسماة = **kwargs.

في التطبيق — تطبيقيا — عرّف الدوال واستدعها

  1. اكتب دالة saluer(nom) تردّ (return) « مرحبا، {nom} ! ». استدعها بأسماء مختلفة واعرض النتيجة.
  2. أضف وسيطا افتراضيا : saluer(nom, politesse="مرحبا"). استدعها مع الحجة الثانية ودونها.
  3. اكتب دالة moyenne(*notes) تقبل عددا متغيرا من الدرجات وتردّ متوسطها. جرّبها بدرجتين ثم 5 درجات.
  4. مثّل النطاق : أنشئ متغيرا في دالة وحاول النيل منه في الخارج (NameError). واستنتج حول المحلي مقابل العمومي.
صرت تنشئ دوال قابلة لإعادة الاستعمال بوسائط وقيم افتراضية وreturn، وتفهم النطاق المحلي للمتغيرات.

نص جاهز للنطق — ارفض print بدلا من return (30 ث)

« أقترح أن تردّ هذه الدالة النتيجة بـ return بدلا من عرضها : فكذا يمكن تخزينها واختبارها وإعادة استعمالها. فـ print لا تنقل شيئا — ويساوي الاستدعاء None ويتعطل الحساب التالي. »

يُقال في مراجعة الشيفرة ؛ واعرض الاستدعاء المخزن قبل/بعد.

نموذج نسخ ولصق — دوال سليمة (return وافتراضي آمن و*args)

def saluer(nom, politesse="مرحبا"):
    return f"{politesse}, {nom} !"
print(saluer("نبيل"))
print(saluer("ياسمين", politesse="أهلا"))
def moyenne(*notes):
    return sum(notes) / len(notes)
print(moyenne(12, 15))
print(moyenne(10, 14, 16, 8, 12))
def ajouter(x, items=None):
    items = items if items is not None else []
    items.append(x)
    return items

متوسطات في الجزائر

كما فعل نبيل : دالة واحدة moyenne(*notes) — فتتغير القاعدة مرة واحدة، وأربعة تقارير صحيحة.

معلومة خارجية للاستعمال

مررها في وسيط صريح : فيوثّق التوقيع الحاجة، وتبقى الدالة قابلة للاختبار معزولة.

قيمة افتراضية

politesse="مرحبا" افتراضيا : فالاستدعاء البسيط يغطي الجاري، والاستدعاء الكامل الخاص.

عدد متغير

*notes لدرجتين ثم 5 درجات، و**options للضبط المسمى : فيبقى التوقيع قصيرا ومرنا.

✓ ممارسات جيدة

  • فعل واحد وعمل واحد وreturn — وليس print أبدا بدلا منه.
  • افتراضيات غير قابلة للتعديل (None وليس [] أو {}).
  • المعطيات في الوسائط وليس في العمومي أبدا.

✗ أخطاء شائعة

  • عرض بـ print بدلا من return (استدعاء يساوي None).
  • كتابة افتراضي قابل للتعديل ([] أو {}) يبقى بين الاستدعاءات.
  • استعمال global للتعديل في الخارج بدلا من وسيط.

النقاط الأساسية

  • تجمع الدالة (def) شيفرة قابلة لإعادة الاستعمال : مبدأ DRY — اسم فعل ومسؤولية واحدة.
  • يردّ return نتيجة قابلة لإعادة الاستعمال ؛ ودونه تردّ الدالة None (ولا يعوّض print عن return).
  • تمنح الوسائط الافتراضية و*args و**kwargs مرونة — والافتراضيات غير القابلة للتعديل فقط.
  • المتغير المعرّف في دالة محلي : غير مرئي في الخارج — والوسائط مدخلا وreturn مخرجا.

تحدي 48 ساعة — طبّق غدا

استخرج حسابا مكررا من سكربتك في دالة (النموذج أعلاه) : وسائط صريحة وreturn وافتراضي آمن. واستبدل print بـ return واختبر بحجتين ثم 5 حجج. تكفي 25 دقيقة.

قائمة الخروج من القسم
  • أعرّف الدوال بوسائط وافتراضي آمن وreturn و*args.
  • أحترم النطاق المحلي — دون عمومية معدلة.
  • أميّز print (تعرض) من return (تنقل).
تقييم ذاتي 1-5 : هل تستقبل دوالي كل شيء في الوسائط ؟هل كل نتيجة معاد استعمالها تخرج بـ return ؟

أسئلة شائعة

ما الفرق بين print() وreturn في دالة ؟

تعرض print() على الشاشة لكنها لا تنقل شيئا إلى بقية البرنامج. ويردّ return قيمة قابلة للاستغلال (تُخزن وتُحسب). فالدالة التي « تعرض » دون « return » لا تصلح إلا للعرض ؛ ولإعادة استعمال النتيجة يلزم return — وإلا ساوى الاستدعاء None.

ما فائدة *args و**kwargs عمليا ؟

يجعلان الدالة مرنة في عدد الحجج. فيجمع *args قيما موضعية في صف (مفيد لمتوسط عدد مجهول من الدرجات) ؛ ويجمع **kwargs أزواج مفتاح=قيمة في قاموس (مفيد لخيارات مسماة مثل sep وtitre...).

تحقّق من فهمك

كم يساوي استدعاء دالة دون return ؟

موارد إضافية (اختياري، للتعمّق أكثر)

اختبار المستوى 1أسئلة جديدة وأصعب للتحقق من مكتسباتك