أهلاً بك في الدرس السابع من رحلتنا نحو بناء وكلاء الذكاء الاصطناعي.
في الدرس الماضي، تعلمنا كيف نستخدم القوائم (Lists) والقواميس (Dictionaries) لتنظيم بياناتنا في هياكل مفيدة. رأينا كيف يمكن لبرنامجنا أن يصبح أكثر قوة عندما يتعامل مع مجموعات من البيانات بدلاً من متغيرات فردية.
مع ازدياد قوة برامجنا، تزداد أيضاً في الطول والتعقيد. قد تجد نفسك تكرر نفس الأسطر من الكود في أماكن متعددة. هذا لا يجعل الكود أطول فحسب، بل يجعل تعديله وإصلاح الأخطاء فيه كابوساً. إذا احتجت لتغيير بسيط، عليك أن تبحث عن كل مكان كررت فيه الكود وتصلحه.
هنا يأتي دور الدوال (Functions). الدوال هي حجر الأساس لتنظيم الكود في أي لغة برمجة، بما في ذلك بايثون. هدفنا في هذا الدرس هو تعلم كيفية تعريف واستدعاء الدوال لتنظيم الكود. سنتعلم كيف نغلف المهام المتكررة في كتل منظمة يمكننا إعادة استخدامها بسهولة.
1. ما هي الدالة ولماذا نستخدمها؟
ببساطة، الدالة هي مجموعة من الأوامر البرمجية التي تؤدي مهمة محددة، ويمكنك إعطاؤها اسماً. بدلاً من كتابة نفس الكود مراراً وتكراراً، يمكنك كتابته مرة واحدة داخل دالة، ثم "استدعاء" هذه الدالة باسمها كلما احتجت لتنفيذ تلك المهمة.
هذا المبدأ، المعروف بـ "لا تكرر نفسك" (Don't Repeat Yourself - DRY)، هو من أهم مبادئ البرمجة النظيفة والفعالة.
الدوال في بايثون - الجزء 1 | Define function
يقدم هذا الفيديو من قناة Two Pi شرحاً ممتازاً لمفهوم الدوال وأهميتها في تنظيم الكود وتقسيمه إلى مهام أصغر وأكثر قابلية للإدارة.
شاهد المقطع من البداية حتى الدقيقة 2:45. ركز على الفوائد الرئيسية لاستخدام الدوال: تقسيم المهام الكبيرة إلى مهام فرعية بسيطة. إعادة استخدام الكود بدلاً من تكراره. تسهيل تعديل الكود وصيانته. جعل الكود أكثر تنظيماً وقابلية للقراءة.
2. تعريف دالة بسيطة واستدعاؤها
الآن بعد أن فهمنا "لماذا"، لنر "كيف". لتعريف دالة في بايثون، نستخدم الكلمة المفتاحية def، متبوعة باسم الدالة الذي نختاره، ثم قوسين ()، وأخيراً نقطتين رأسيتين :. الأوامر التي تنتمي للدالة يجب أن تكون مُزاحة (indented) بمسافة بادئة، تماماً كما فعلنا مع الحلقات والجمل الشرطية.
دعنا نرى كيف يتم ذلك عملياً.
الدوال في بايثون - الجزء 1 | Define function
يكمل هذا المقطع شرح كيفية تعريف دالة بسيطة واستدعائها. لاحظ جيداً أن الكود داخل الدالة لا يتم تنفيذه إلا عند استدعائها بشكل صريح.
شاهد من الدقيقة 2:45 حتى 4:54. انتبه إلى: الصيغة: def function_name(): المسافة البادئة (Indentation): كيف تحدد الأوامر التابعة للدالة. الاستدعاء (Calling): كتابة اسم الدالة متبوعاً بقوسين () لتنفيذها.
للتلخيص، العملية تتم على خطوتين:
- التعريف (Definition): ننشئ الدالة ونحدد ماذا ستفعل.
# تعريف الدالة def say_hello(): print("مرحباً بك في عالم الدوال!") - الاستدعاء (Call): نطلب من البرنامج تنفيذ الكود الموجود داخل الدالة.
الناتج:# استدعاء الدالة say_hello()مرحباً بك في عالم الدوال!
إذا لم نستدعِ الدالة say_hello()، فلن يتم طباعة أي شيء على الإطلاق.
3. تمرير المعلومات إلى الدوال (المعاملات والوسائط)
الدوال تصبح أكثر فائدة عندما يمكنها استقبال بيانات والعمل عليها. يمكننا "تمرير" بيانات إلى الدالة عند استدعائها.
- المعامل (Parameter): هو المتغير الذي نضعه بين القوسين عند تعريف الدالة. إنه بمثابة مكان مخصص لاستقبال قيمة.
- الوسيط (Argument): هي القيمة الفعلية التي نرسلها إلى الدالة عند استدعائها.
الدوال في بايثون - الجزء 1 | Define function
يشرح هذا المقطع كيفية جعل الدوال أكثر مرونة عبر استخدام المعاملات (Parameters) لاستقبال البيانات.
شاهد من الدقيقة 4:54 حتى 7:11. ركز على كيفية: تعريف دالة بمعامل واحد (name). استدعاء الدالة مع وسيط ('أحمد'). تعريف دالة بأكثر من معامل واحد وفصلها بفاصلة.
مثال:
# 'name' هنا هو المعامل (Parameter)
def greet_person(name):
print(f"أهلاً بك، {name}!")
# 'علي' و 'فاطمة' هنا هما الوسيطان (Arguments)
greet_person("علي")
greet_person("فاطمة")
الناتج:
أهلاً بك، علي!
أهلاً بك، فاطمة!
لاحظ كيف أعدنا استخدام نفس الدالة greet_person لأداء نفس المهمة (الترحيب) ولكن ببيانات مختلفة في كل مرة.
اختبر فهمك!
اكتب دالة باسم show_info تأخذ معاملين: name و age. عند استدعاء الدالة، يجب أن تطبع جملة مثل: "[الاسم] يبلغ من العمر [العمر] عاماً.".
ثم استدعِ الدالة مرتين ببيانات مختلفة.
أظهر الحل
# تعريف الدالة
def show_info(name, age):
print(f"{name} يبلغ من العمر {age} عاماً.")
# استدعاء الدالة
show_info("سالم", 28)
show_info("هند", 32)
الناتج المتوقع:
سالم يبلغ من العمر 28 عاماً.
هند يبلغ من العمر 32 عاماً.
4. إعادة قيمة من الدالة (The return Statement)
في كثير من الأحيان، لا نريد أن تقوم الدالة بالطباعة على الشاشة فقط، بل نريدها أن تقوم بعملية حسابية وتعيد لنا النتيجة لنستخدمها لاحقاً في برنامجنا. هنا نستخدم الكلمة المفتاحية return.
عندما يصل التنفيذ إلى return، تتوقف الدالة فوراً وتعيد القيمة المحددة.

لنشاهد شرحاً عملياً لذلك.
الدوال في بايثون - الجزء 1 | Define function
يوضح هذا المقطع أهمية عبارة return وكيف تسمح للدوال بإرجاع نتائج يمكننا تخزينها في متغيرات والاستفادة منها في باقي أجزاء البرنامج.
شاهد من الدقيقة 7:11 حتى 9:43. ركز على: الفرق بين دالة تطبع قيمة ودالة تعيدها. استخدام return لإرجاع القيمة المحسوبة. كيفية استقبال القيمة المعادة في متغير عند استدعاء الدالة.
مثال على دالة تقوم بعملية حسابية وتعيد النتيجة:
# دالة تجمع رقمين وتعيد الناتج
def add_numbers(x, y):
total = x + y
return total
# استدعاء الدالة وتخزين النتيجة في متغير
sum_result = add_numbers(10, 5)
print(f"ناتج الجمع هو: {sum_result}")
print(f"يمكننا استخدام الناتج في عملية أخرى: {sum_result * 2}")
الناتج:
ناتج الجمع هو: 15
يمكننا استخدام الناتج في عملية أخرى: 30
الدوال التي تعيد قيماً (return) هي الأكثر شيوعاً وقوة، لأنها تسمح لنا ببناء برامج معقدة عبر ربط مخرجات دالة كمدخلات لدالة أخرى.
5. توثيق الدوال (Docstrings)
من الممارسات الجيدة أن تصف ما تفعله الدالة داخلها مباشرةً. هذا يساعدك (ويساعد المبرمجين الآخرين) على فهم الغرض من الدالة دون الحاجة لقراءة كل أسطر الكود. يتم ذلك باستخدام ما يسمى سلسلة التوثيق النصية (Docstring)، وهي نص تضعه بين ثلاث علامات اقتباس مزدوجة """ في بداية الدالة مباشرة.
def calculate_average(numbers):
"""
تحسب هذه الدالة المتوسط الحسابي لقائمة من الأرقام.
تأخذ قائمة أرقام كمدخل (list) وتعيد المتوسط (float).
إذا كانت القائمة فارغة، تعيد 0.
"""
if not numbers:
return 0
total = sum(numbers)
average = total / len(numbers)
return average
# الآن يمكننا استخدام الدالة
grades = [85, 90, 78, 92]
avg = calculate_average(grades)
print(f"المتوسط هو: {avg}")
هذه العادة ستكون مفيدة جداً عندما تبدأ في بناء مشاريع أكبر، مثل وكلاء الذكاء الاصطناعي.
لترسيخ المفاهيم والمصطلحات الجديدة التي تعلمناها، يمكنك قراءة هذه المقالة كمرجع.
تقدم هذه المقالة من أكاديمية حسوب مراجعة نصية ممتازة لأساسيات الدوال في بايثون، وهي تكمل ما شاهدناه في الفيديو.
اقرأ الأجزاء التالية من المقال: المقدمة (حتى "عبارة def مع معاملات") لترى مثالاً آخر لتعريف واستدعاء دالة. عبارة def مع معاملات: لفهم الفرق بين المعامل (parameter) والوسيط (argument). التعريف والاستدعاء والتمرير...: هذا القسم يلخص المصطلحات بشكل جيد. القيم المعادة وعبارة return: لترسيخ مفهوم إعادة القيم.
تمرين تطبيقي شامل
في الدرس الماضي، تعلمنا عن القواميس. لنكتب دالة تتعامل معها!
اكتب دالة باسم get_product_status تأخذ قاموساً يمثل منتجاً كمدخل. القاموس يحتوي على مفتاحين: 'name' (اسم المنتج) و 'quantity' (الكمية المتاحة).
يجب أن تقوم الدالة بالآتي:
- تفحص قيمة
'quantity'. - إذا كانت الكمية أكبر من 0، يجب أن تعيد (
return) سلسلة نصية بالصيغة:"[اسم المنتج]" متوفر في المخزون. - إذا كانت الكمية تساوي 0، يجب أن تعيد (
return) سلسلة نصية بالصيغة:"[اسم المنتج]" غير متوفر حالياً.
بعد تعريف الدالة، قم بإنشاء قاموسين لمنتجين مختلفين، واستدعِ الدالة لكل منهما، ثم اطبع النتيجة المعادة.
أظهر الحل
def get_product_status(product_dict):
"""
تفحص هذه الدالة حالة توفر منتج بناءً على قاموس معلوماته.
"""
product_name = product_dict['name']
product_quantity = product_dict['quantity']
if product_quantity > 0:
return f'"{product_name}" متوفر في المخزون.'
else:
return f'"{product_name}" غير متوفر حالياً.'
# إنشاء بيانات المنتجات
product1 = {'name': 'لابتوب', 'quantity': 15}
product2 = {'name': 'شاشة عرض', 'quantity': 0}
# استدعاء الدالة لكل منتج وطباعة النتيجة
status1 = get_product_status(product1)
print(status1)
status2 = get_product_status(product2)
print(status2)
الناتج المتوقع:
"لابتوب" متوفر في المخزون.
"شاشة عرض" غير متوفر حالياً.
ملخص الدرس
ممتاز! لقد أضفت اليوم إلى صندوق أدواتك البرمجية واحدة من أهم الأدوات على الإطلاق.
- الدوال (Functions) هي كتل من الكود القابل لإعادة الاستخدام، تساعدنا على تنظيم برامجنا وتجنب التكرار.
- نُعرّف الدالة باستخدام الكلمة المفتاحية
def. - نستدعي الدالة بكتابة اسمها متبوعاً بقوسين
(). - يمكننا تمرير بيانات للدالة عبر المعاملات (Parameters).
- يمكن للدالة أن تعيد نتيجة باستخدام الكلمة المفتاحية
return.
ما التالي؟
الآن بعد أن تعلمنا كيفية كتابة الدوال، ماذا يحدث إذا حاول مستخدم برنامجنا إدخال قيمة خاطئة؟ أو إذا فشلت الدالة في أداء مهمتها لسبب ما؟ حالياً، سينهار البرنامج ويتوقف. في الدرس القادم، سنتعلم كيفية التعامل مع هذه الأخطاء بأناقة باستخدام كتل try/except، مما يجعل برامجنا أكثر قوة ومتانة.