ما هي الدوال؟
الدوال هي كتل من الكود القابل لإعادة الاستخدام تؤدي مهمة محددة. تساعدك على تنظيم الكود، تجنب التكرار، وجعل البرامج أسهل للفهم والصيانة.
Python
تعريف واستدعاء الدوال
# تعريف دالة بسيطة
def تحية():
"""دالة تحية بسيطة."""
print("مرحباً بالعالم!")
# استدعاء الدالة
تحية() # المخرج: مرحباً بالعالم!
تحية() # يمكن استدعاؤها عدة مرات
# دالة مع معامل
def تحية_شخص(الاسم):
"""تحية شخص معين."""
print(f"مرحباً يا {الاسم}!")
تحية_شخص("أحمد") # مرحباً يا أحمد!
تحية_شخص("سارة") # مرحباً يا سارة!
🔍 تشريح الدالة
def- الكلمة المفتاحية لتعريف الدالةاسم_الدالة- يتبع قواعد تسمية المتغيرات(المعاملات)- المدخلات التي تقبلها الدالة:- تبدأ جسم الدالة"""نص توثيقي"""- وصف اختياري للدالة- الكود المُزاح - جسم الدالة
المعاملات والوسيطات
Python
الفرق بين المعاملات والوسيطات
# المعاملات vs الوسيطات:
# - المعاملات: المتغيرات في تعريف الدالة
# - الوسيطات: القيم المُمررة عند استدعاء الدالة
def جمع(أ, ب): # أ و ب هي معاملات
return أ + ب
الناتج = جمع(5, 3) # 5 و 3 هي وسيطات
print(الناتج) # 8
# معاملات متعددة
def تقديم(الاسم, العمر, المدينة):
print(f"أنا {الاسم}، عمري {العمر} سنة، من {المدينة}")
تقديم("أحمد", 25, "القاهرة")
# الوسيطات الموضعية (الترتيب مهم)
تقديم("سارة", 30, "الرياض") # الترتيب الصحيح
# تقديم(30, "سارة", "الرياض") # خطأ! العمر سيكون 30، والاسم سيكون "سارة"
القيم المُرجعة
Python
إرجاع القيم من الدوال
# إرجاع قيمة
def تربيع(ن):
return ن ** 2
الناتج = تربيع(5)
print(الناتج) # 25
# دالة بدون return تُرجع None
def تحية(الاسم):
print(f"مرحباً يا {الاسم}")
الناتج = تحية("أحمد")
print(الناتج) # None
# إرجاع قيم متعددة (كـ tuple)
def قسمة_وباقي(أ, ب):
خارج_القسمة = أ // ب
الباقي = أ % ب
return خارج_القسمة, الباقي
ق, ب = قسمة_وباقي(17, 5)
print(f"17 ÷ 5 = {ق} والباقي {ب}") # 17 ÷ 5 = 3 والباقي 2
# الإرجاع المبكر
def هل_بالغ(العمر):
if العمر < 0:
return None # عمر غير صالح
if العمر >= 18:
return True
return False
print(هل_بالغ(25)) # True
print(هل_بالغ(15)) # False
print(هل_بالغ(-5)) # None
المعاملات الافتراضية
Python
القيم الافتراضية للمعاملات
# قيم افتراضية للمعاملات
def تحية(الاسم, رسالة_ترحيب="مرحباً"):
print(f"{رسالة_ترحيب} يا {الاسم}!")
تحية("أحمد") # مرحباً يا أحمد!
تحية("سارة", "أهلاً") # أهلاً يا سارة!
تحية("محمد", "السلام عليكم") # السلام عليكم يا محمد!
# معاملات افتراضية متعددة
def إنشاء_ملف_شخصي(الاسم, العمر=0, المدينة="غير محدد", نشط=True):
return {
"الاسم": الاسم,
"العمر": العمر,
"المدينة": المدينة,
"نشط": نشط
}
print(إنشاء_ملف_شخصي("أحمد"))
# {'الاسم': 'أحمد', 'العمر': 0, 'المدينة': 'غير محدد', 'نشط': True}
print(إنشاء_ملف_شخصي("سارة", 25, "القاهرة"))
# {'الاسم': 'سارة', 'العمر': 25, 'المدينة': 'القاهرة', 'نشط': True}
⚠️ تحذير: المعاملات الافتراضية المتغيرة
لا تستخدم كائنات متغيرة (قوائم، قواميس) كقيم افتراضية!
# خطأ - قيمة افتراضية متغيرة
def إضافة_عنصر(عنصر, القائمة=[]):
القائمة.append(عنصر)
return القائمة
print(إضافة_عنصر("أ")) # ['أ']
print(إضافة_عنصر("ب")) # ['أ', 'ب'] - غير متوقع!
# صحيح - استخدم None
def إضافة_عنصر(عنصر, القائمة=None):
if القائمة is None:
القائمة = []
القائمة.append(عنصر)
return القائمة
الوسيطات المُسماة
Python
استخدام الوسيطات المُسماة
# الوسيطات المُسماة (الترتيب غير مهم)
def إنشاء_مستخدم(الاسم, العمر, البريد, نشط=True):
return {
"الاسم": الاسم,
"العمر": العمر,
"البريد": البريد,
"نشط": نشط
}
# جميعها موضعية
مستخدم1 = إنشاء_مستخدم("أحمد", 25, "ahmed@example.com")
# جميعها مُسماة
مستخدم2 = إنشاء_مستخدم(
الاسم="سارة",
العمر=30,
البريد="sara@example.com",
نشط=False
)
# مختلطة (الموضعية أولاً، ثم المُسماة)
مستخدم3 = إنشاء_مستخدم("محمد", 35, البريد="mohamed@example.com")
# الوسيطات المُسماة يمكن أن تكون بأي ترتيب
مستخدم4 = إنشاء_مستخدم(
البريد="diana@example.com",
الاسم="ديانا",
العمر=28
)
print(مستخدم4) # الترتيب لا يهم للوسيطات المُسماة
النصوص التوثيقية (Docstrings)
Python
توثيق الدوال
def حساب_المساحة(الطول, العرض):
"""
حساب مساحة المستطيل.
المعاملات:
الطول (float): طول المستطيل.
العرض (float): عرض المستطيل.
الإرجاع:
float: مساحة المستطيل.
مثال:
>>> حساب_المساحة(5, 3)
15
"""
return الطول * العرض
# الوصول للنص التوثيقي
print(حساب_المساحة.__doc__)
# استخدام help()
help(حساب_المساحة)
# نص توثيقي من سطر واحد للدوال البسيطة
def تربيع(ن):
"""إرجاع مربع ن."""
return ن ** 2
النطاق والمتغيرات
Python
النطاق المحلي والعام
# النطاق المحلي vs العام
متغير_عام = "أنا عام"
def دالتي():
متغير_محلي = "أنا محلي"
print(متغير_عام) # يمكن قراءة العام
print(متغير_محلي) # يمكن قراءة المحلي
دالتي()
print(متغير_عام) # يعمل
# print(متغير_محلي) # NameError - غير متاح
# تعديل المتغيرات العامة
العداد = 0
def زيادة():
global العداد # إعلان نية تعديل المتغير العام
العداد += 1
زيادة()
زيادة()
print(العداد) # 2
# طريقة أفضل: تجنب الحالة العامة
def زيادة_قيمة(القيمة):
return القيمة + 1
العداد = 0
العداد = زيادة_قيمة(العداد)
العداد = زيادة_قيمة(العداد)
print(العداد) # 2
# إخفاء المتغير
س = 10
def دالة():
س = 20 # ينشئ متغير محلي جديد، لا يعدل العام
print(f"داخل: {س}")
دالة() # داخل: 20
print(f"خارج: {س}") # خارج: 10
الدوال المُدمجة الشائعة
Python
دوال بايثون المُدمجة
# تحويل الأنواع
int("42") # 42
float("3.14") # 3.14
str(100) # "100"
bool(1) # True
list("أبج") # ['أ', 'ب', 'ج']
# دوال رياضية
abs(-5) # 5
round(3.7) # 4
round(3.14159, 2) # 3.14
pow(2, 3) # 8
min(1, 2, 3) # 1
max(1, 2, 3) # 3
sum([1, 2, 3]) # 6
# دوال التسلسلات
len([1, 2, 3]) # 3
sorted([3, 1, 2]) # [1, 2, 3]
reversed([1, 2]) # مُكرر
list(reversed([1, 2, 3])) # [3, 2, 1]
# مساعدات التكرار
range(5) # 0, 1, 2, 3, 4
enumerate(['أ', 'ب']) # (0, 'أ'), (1, 'ب')
zip([1, 2], ['أ', 'ب']) # (1, 'أ'), (2, 'ب')
# الإدخال/الإخراج
print("مرحباً") # إخراج
# input("الاسم: ") # الحصول على إدخال المستخدم
# فحص الأنواع
type(42) #
isinstance(42, int) # True
# معلومات الكائن
id(42) # عنوان الذاكرة
dir([]) # قائمة الخصائص/الدوال
help(print) # التوثيق
🎯 تحدي: محول درجات الحرارة
أنشئ دوالاً للتحويل بين مقاييس درجات الحرارة:
مئوي_إلى_فهرنهايت(م)فهرنهايت_إلى_مئوي(ف)مئوي_إلى_كلفن(م)- دالة رئيسية
تحويل_حرارة(القيمة, من_مقياس, إلى_مقياس)
💡 عرض الحل
def مئوي_إلى_فهرنهايت(م):
"""تحويل مئوي إلى فهرنهايت."""
return (م * 9/5) + 32
def فهرنهايت_إلى_مئوي(ف):
"""تحويل فهرنهايت إلى مئوي."""
return (ف - 32) * 5/9
def مئوي_إلى_كلفن(م):
"""تحويل مئوي إلى كلفن."""
return م + 273.15
def كلفن_إلى_مئوي(ك):
"""تحويل كلفن إلى مئوي."""
return ك - 273.15
def تحويل_حرارة(القيمة, من_مقياس, إلى_مقياس):
"""
تحويل درجة الحرارة بين المقاييس.
المقاييس: 'م' (مئوي), 'ف' (فهرنهايت), 'ك' (كلفن)
"""
من_مقياس = من_مقياس.upper()
إلى_مقياس = إلى_مقياس.upper()
# تحويل إلى مئوي أولاً
if من_مقياس == 'ف':
مئوي = فهرنهايت_إلى_مئوي(القيمة)
elif من_مقياس == 'ك':
مئوي = كلفن_إلى_مئوي(القيمة)
else:
مئوي = القيمة
# تحويل من مئوي إلى الهدف
if إلى_مقياس == 'ف':
return مئوي_إلى_فهرنهايت(مئوي)
elif إلى_مقياس == 'ك':
return مئوي_إلى_كلفن(مئوي)
return مئوي
# اختبار
print(f"0°م = {تحويل_حرارة(0, 'م', 'ف'):.1f}°ف")
print(f"100°م = {تحويل_حرارة(100, 'م', 'ك'):.1f}ك")
print(f"32°ف = {تحويل_حرارة(32, 'ف', 'م'):.1f}°م")
🎯 تحدي: دوال الآلة الحاسبة
أنشئ آلة حاسبة بسيطة بدوال لـ:
- العمليات الأساسية: جمع، طرح، ضرب، قسمة
- دالة
حساب(أ, ب, العملية) - التعامل مع القسمة على صفر بشكل سليم
💡 عرض الحل
def جمع(أ, ب):
"""جمع عددين."""
return أ + ب
def طرح(أ, ب):
"""طرح ب من أ."""
return أ - ب
def ضرب(أ, ب):
"""ضرب عددين."""
return أ * ب
def قسمة(أ, ب):
"""قسمة أ على ب. يُرجع None إذا كان ب صفراً."""
if ب == 0:
return None
return أ / ب
def حساب(أ, ب, العملية):
"""
تنفيذ العملية الحسابية.
العمليات: 'جمع', 'طرح', 'ضرب', 'قسمة'
أيضاً يقبل: '+', '-', '*', '/'
"""
العمليات = {
'جمع': جمع, '+': جمع,
'طرح': طرح, '-': طرح,
'ضرب': ضرب, '*': ضرب,
'قسمة': قسمة, '/': قسمة
}
دالة_العملية = العمليات.get(العملية)
if دالة_العملية is None:
return f"عملية غير معروفة: {العملية}"
الناتج = دالة_العملية(أ, ب)
if الناتج is None:
return "خطأ: القسمة على صفر"
return الناتج
# اختبار
print(حساب(10, 5, 'جمع')) # 15
print(حساب(10, 5, '-')) # 5
print(حساب(10, 5, 'ضرب')) # 50
print(حساب(10, 0, 'قسمة')) # رسالة خطأ
📝 ملخص الدرس
- الدوال تُعرَّف بـ
def اسم_الدالة(المعاملات): - استخدم
returnلإرسال القيم للمُستدعي - المعاملات الافتراضية توفر قيم احتياطية
- الوسيطات المُسماة تسمح بتمرير المعاملات بالاسم
- النصوص التوثيقية توثق ما تفعله الدوال
- المتغيرات داخل الدوال محلية بشكل افتراضي
- تجنب الوسيطات الافتراضية المتغيرة (استخدم
Noneبدلاً منها)