الدوال في بايثون: اكتب الكود مرة واستخدمه ألف مرة

تعلّم تعريف الدوال في بايثون بـ def، واستدعاءها، وتمرير المعاملات إليها، وإرجاع النتائج بـ return، والفرق بين print و return.

تخيّل أنك تكتب برنامجًا يرحّب بكل لاعب في فريقك. عندك عشرة لاعبين، فهل تكتب نفس أسطر الترحيب عشر مرات؟ وماذا لو أردت تغيير كلمة واحدة في الترحيب؟ ستعدّلها في عشرة أماكن! في هذا الدرس ستتعلّم كيف تكتب الكود مرة واحدة، ثم تستخدمه متى شئت وبأي عدد تريده.

🎯 ماذا ستتعلم؟

بنهاية هذا الدرس ستكون قادرًا على:

  • تعريف دالة جديدة بالكلمة def.
  • استدعاء الدالة وتشغيلها في أي مكان من برنامجك.
  • تمرير معلومات إلى الدالة عن طريق المعاملات.
  • إرجاع نتيجة من الدالة بـ return واستخدامها في متغيّر.
  • التفريق بين الدالة التي تطبع والدالة التي تُرجع قيمة.

🧰 ماذا تحتاج قبل أن تبدأ؟

يجب أن تعرف المتغيّرات وأنواع البيانات، والقوائم، والشروط، والحلقات. كل الأمثلة تعمل في مترجم بايثون في المتصفح بدون تثبيت.

الفكرة ببساطة

فكّر في آلة العصير في المطبخ. تضع فيها الفاكهة من الأعلى، تضغط الزر، فيخرج العصير من الأسفل. لا تحتاج أن تعرف ما يحدث بداخلها، ولا تصنع آلة جديدة لكل كوب.

الدالة (function) في بايثون هي آلة صغيرة مثل هذه. تعطيها شيئًا، تقوم بعملها، ثم تعطيك نتيجة. تصنع الآلة مرة واحدة، وتستخدمها في كل مرة تحتاجها.

أنت في الحقيقة تستخدم الدوال منذ أول درس. print() دالة تأخذ نصًا وتعرضه، وlen() دالة تأخذ قائمة وتعطيك عدد عناصرها. اليوم ستصنع دوالك الخاصة.

الخطوة 1: تعريف دالة بـ def

لصنع دالة، اكتب الكلمة def، ثم اسم الدالة، ثم قوسين ()، ثم نقطتين :. الأسطر التي تحتها بمسافة بادئة هي جسم الدالة، أي ما تفعله عند تشغيلها.

def greet():
    print("أهلًا بك في الفريق!")
    print("نتمنى لك موسمًا رائعًا")

print("انتهى تعريف الدالة")
انتهى تعريف الدالة

لاحظ أن الترحيب لم يُطبع! ظهر السطر الأخير فقط. لأن التعريف يصنع الآلة ولا يشغّلها. كأنك اشتريت آلة العصير ووضعتها في المطبخ، لكنك لم تضغط الزر بعد.

الخطوة 2: استدعاء الدالة

لتشغيل الدالة، اكتب اسمها متبوعًا بقوسين. هذا يسمّى الاستدعاء (call). ويمكنك استدعاء الدالة نفسها مرات كثيرة.

def greet():
    print("أهلًا بك في الفريق!")
    print("نتمنى لك موسمًا رائعًا")

greet()
greet()
greet()
أهلًا بك في الفريق!
نتمنى لك موسمًا رائعًا
أهلًا بك في الفريق!
نتمنى لك موسمًا رائعًا
أهلًا بك في الفريق!
نتمنى لك موسمًا رائعًا

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

تذكّر قاعدة مهمة: يجب أن تعرّف الدالة قبل أن تستدعيها. بايثون تقرأ البرنامج من الأعلى إلى الأسفل، ولا تعرف الآلة قبل أن تصنعها.

الخطوة 3: تمرير معلومات بالمعاملات

الترحيب السابق واحد للجميع. لكن ماذا لو أردنا أن نذكر اسم كل لاعب؟ هنا نحتاج المعامل (parameter)، وهو متغيّر تكتبه بين قوسي الدالة عند تعريفها.

عند الاستدعاء، تضع القيمة بين القوسين، وتسمّى هذه القيمة الوسيط (argument). بايثون تأخذ الوسيط وتضعه داخل المعامل تلقائيًا.

def greet(player):
    print("أهلًا بك يا", player)

greet("سالم")
greet("نورة")
greet("خالد")
أهلًا بك يا سالم
أهلًا بك يا نورة
أهلًا بك يا خالد

في الاستدعاء الأول صار player هو “سالم”، وفي الثاني “نورة”، وهكذا. الدالة واحدة، لكنها تعمل مع أي اسم تعطيها إياه.

ويمكن أن تأخذ الدالة أكثر من معامل، تفصل بينها بفاصلة. الترتيب مهم: أول وسيط يذهب إلى أول معامل، والثاني إلى الثاني.

def show_score(player, score):
    print("عند", player, score, "نقطة")

show_score("سالم", 120)
show_score("نورة", 95)
عند سالم 120 نقطة
عند نورة 95 نقطة

وتعمل الدوال بشكل رائع مع الحلقات. هنا نرحّب بكل لاعب في القائمة بسطر واحد داخل الحلقة:

def greet(player):
    print("أهلًا بك يا", player)

team = ["سالم", "نورة", "خالد", "ليلى"]
for member in team:
    greet(member)
أهلًا بك يا سالم
أهلًا بك يا نورة
أهلًا بك يا خالد
أهلًا بك يا ليلى

الخطوة 4: إرجاع نتيجة بـ return

كل الدوال السابقة تطبع فقط. لكن أحيانًا تريد من الدالة أن تحسب شيئًا وتعطيك النتيجة، لتستخدمها لاحقًا. هنا تأتي الكلمة return، وتعني “أرجع هذه القيمة إلى من استدعاني”.

def add(a, b):
    return a + b

total = add(10, 25)
print(total)
print(add(3, 4) * 2)
35
14

في السطر total = add(10, 25) استدعينا الدالة، فحسبت المجموع وأرجعت 35. ثم وضعنا 35 في المتغيّر total. وفي السطر الأخير استخدمنا النتيجة مباشرة في عملية ضرب.

هذا هو الفرق الكبير: print() تعرض القيمة على الشاشة ثم تختفي. أما return فتعطيك القيمة لتحفظها أو تحسب بها أو تطبعها كما تشاء.

إليك مثالًا أطول. دالة تحسب متوسط درجات الطالب في قائمة:

def average(grades):
    total = 0
    for grade in grades:
        total = total + grade
    return total / len(grades)

math_grades = [90, 85, 100]
science_grades = [70, 80]
print("متوسط الرياضيات:", average(math_grades))
print("متوسط العلوم:", average(science_grades))
متوسط الرياضيات: 91.66666666666667
متوسط العلوم: 75.0

ومهم أن تعرف: عندما تصل بايثون إلى return، تخرج من الدالة فورًا. أي سطر بعدها داخل الدالة لن يعمل.

الخطوة 5: ماذا ترجع الدالة بدون return؟

ماذا لو حفظت نتيجة دالة لا تحتوي على return؟ جرّب بنفسك:

def say_hello(name):
    print("مرحبًا", name)

result = say_hello("مريم")
print(result)
مرحبًا مريم
None

الدالة طبعت الترحيب، لكنها لم تُرجع شيئًا. لذلك حصل result على القيمة الخاصة None، وتعني “لا شيء”. هذا ليس خطأ، لكنه مفاجأة شائعة للمبتدئين.

القاعدة: إن أردت استخدام النتيجة لاحقًا، استعمل return. وإن أردت عرضها فقط، يكفي print().

🚀 للمتقدمين: يمكنك إعطاء المعامل قيمة افتراضية تُستخدم إذا لم يرسل المستدعي وسيطًا. اكتب def greet(player="صديقي"): ثم استدعِ greet() بدون وسيط، وستطبع “أهلًا بك يا صديقي”. ويمكن للدالة أن تُرجع أكثر من قيمة بفاصلة: return total, count، ثم تستقبلهما بـ total, count = my_function().

⚠️ أخطاء شائعة

الأخطاء طبيعية جدًا في البداية، وكل مبرمج مرّ بها. إليك ثلاثة تقابلها كثيرًا مع الدوال:

1. استدعاء الدالة قبل تعريفها

❌ هذا الكود يتوقف بخطأ
greet("سالم")

def greet(player):
    print("أهلًا بك يا", player)

NameError: name 'greet' is not defined

بايثون وصلت إلى الاستدعاء قبل أن تعرف الدالة. ضع التعريف في الأعلى دائمًا:

# ✅
def greet(player):
    print("أهلًا بك يا", player)

greet("سالم")
أهلًا بك يا سالم

2. نسيان الأقواس عند الاستدعاء

❌
def greet():
    print("أهلًا!")

greet

هذا الكود لا يتوقف، لكنه لا يطبع شيئًا أيضًا. بدون القوسين أنت تشير إلى الدالة فقط ولا تشغّلها. الأقواس هي زر التشغيل:

# ✅
def greet():
    print("أهلًا!")

greet()
أهلًا!

3. عدد الوسائط لا يطابق عدد المعاملات

❌
def show_score(player, score):
    print("عند", player, score, "نقطة")

show_score("سالم")
TypeError: show_score() missing 1 required positional argument: 'score'

الدالة تنتظر قيمتين، وأرسلت واحدة فقط. الرسالة تخبرك بالضبط باسم المعامل الناقص. أرسل كل القيم المطلوبة:

# ✅
def show_score(player, score):
    print("عند", player, score, "نقطة")

show_score("سالم", 120)
عند سالم 120 نقطة

🧪 جرّب بنفسك

التحدي 1: مساحة الغرفة

اكتب دالة اسمها area تأخذ الطول والعرض، وتُرجع مساحة الغرفة. ثم استخدمها لطباعة مساحة غرفتين مختلفتين.

# أكمل الدالة لتُرجع الطول مضروبًا في العرض
def area(length, width):
    return 0

print(area(4, 3))
print(area(5, 6))
0
0
💡 اضغط لرؤية الحل
def area(length, width):
    return length * width

print(area(4, 3))
print(area(5, 6))
12
30

التحدي 2: ناجح أم يحتاج مراجعة؟

اكتب دالة check_grade تأخذ درجة، وتُرجع النص “ناجح” إذا كانت الدرجة 50 أو أكثر، وإلا تُرجع “يحتاج مراجعة”. ثم استخدمها مع حلقة على قائمة درجات.

# أكمل الدالة باستخدام if و else
def check_grade(grade):
    return ""

grades = [80, 45, 50, 30]
for grade in grades:
    print(grade, check_grade(grade))
80 
45 
50 
30 
💡 اضغط لرؤية الحل
def check_grade(grade):
    if grade >= 50:
        return "ناجح"
    else:
        return "يحتاج مراجعة"

grades = [80, 45, 50, 30]
for grade in grades:
    print(grade, check_grade(grade))
80 ناجح
45 يحتاج مراجعة
50 ناجح
30 يحتاج مراجعة

التحدي 3: أعلى نقاط في اللعبة

اكتب دالة highest تأخذ قائمة نقاط، وتُرجع أكبر رقم فيها بدون استخدام max(). ابدأ بمتغيّر يحمل أول عنصر، ثم مرّ على القائمة وحدّثه كلما وجدت رقمًا أكبر.

# أكمل الدالة لتُرجع أكبر رقم في القائمة
def highest(scores):
    best = scores[0]
    return best

print(highest([40, 95, 60, 88]))
print(highest([12, 7, 30]))
40
12
💡 اضغط لرؤية الحل
def highest(scores):
    best = scores[0]
    for score in scores:
        if score > best:
            best = score
    return best

print(highest([40, 95, 60, 88]))
print(highest([12, 7, 30]))
95
30

✅ اختبر نفسك

  1. أي كلمة تستخدمها لتعريف دالة جديدة في بايثون؟

    • أ) function
    • ب) def
    • ج) return
  2. عرّفنا الدالة def double(n): return n * 2. ماذا يطبع print(double(6))؟

    • أ) 12
    • ب) 6
    • ج) None
  3. صح أم خطأ: الدالة التي لا تحتوي على return تُرجع القيمة None.

💡 اضغط لرؤية الإجابات
  1. ب) def، وهي اختصار لكلمة define أي “عرّف”.
  2. أ) 12، لأن الدالة تُرجع 6 مضروبة في 2.
  3. صح. كل دالة بدون return تُرجع None تلقائيًا.

📝 الخلاصة

  • الدالة كود تكتبه مرة واحدة بـ def، وتستدعيه بأي عدد تريده باسمه والقوسين.
  • عرّف الدالة دائمًا قبل أن تستدعيها.
  • المعاملات تستقبل القيم التي ترسلها عند الاستدعاء، والترتيب مهم.
  • return تُرجع نتيجة تستطيع حفظها في متغيّر أو استخدامها في حساب آخر.
  • print() تعرض فقط، والدالة بدون return تُرجع None.

⏭️ الخطوة التالية

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