1.4الدوال والوسائط والنطاق
الأساسي في 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 لمتغير محلي طُلب في الخارج : فالمحلي مقابل العمومي محسوم.
🔎 مثال ملموس — 🔎 مثال ملموس — فخ القائمة الافتراضية
الخلل الشهير، كما واجهه نبيل في متوسطاته.
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.
في التطبيق — تطبيقيا — عرّف الدوال واستدعها
- اكتب دالة saluer(nom) تردّ (return) « مرحبا، {nom} ! ». استدعها بأسماء مختلفة واعرض النتيجة.
- أضف وسيطا افتراضيا : saluer(nom, politesse="مرحبا"). استدعها مع الحجة الثانية ودونها.
- اكتب دالة moyenne(*notes) تقبل عددا متغيرا من الدرجات وتردّ متوسطها. جرّبها بدرجتين ثم 5 درجات.
- مثّل النطاق : أنشئ متغيرا في دالة وحاول النيل منه في الخارج (NameError). واستنتج حول المحلي مقابل العمومي.
نص جاهز للنطق — ارفض 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 (تنقل).
أسئلة شائعة
ما الفرق بين print() وreturn في دالة ؟
تعرض print() على الشاشة لكنها لا تنقل شيئا إلى بقية البرنامج. ويردّ return قيمة قابلة للاستغلال (تُخزن وتُحسب). فالدالة التي « تعرض » دون « return » لا تصلح إلا للعرض ؛ ولإعادة استعمال النتيجة يلزم return — وإلا ساوى الاستدعاء None.
ما فائدة *args و**kwargs عمليا ؟
يجعلان الدالة مرنة في عدد الحجج. فيجمع *args قيما موضعية في صف (مفيد لمتوسط عدد مجهول من الدرجات) ؛ ويجمع **kwargs أزواج مفتاح=قيمة في قاموس (مفيد لخيارات مسماة مثل sep وtitre...).
كم يساوي استدعاء دالة دون return ؟