الدوال في بايثون (Functions)
تخيل أنك تبني منزلاً وتحتاج لتركيب 50 نافذة. هل ستكتب تعليمات التركيب من الصفر لكل نافذة؟ بالطبع لا. ستكتب التعليمات مرة واحدة ثم تطبقها 50 مرة. هذا بالضبط مفهوم الدوال في البرمجة: كتابة كود مرة واحدة وإعادة استخدامه عند الحاجة.
الدوال (Functions) هي حجر الأساس في البرمجة المنظمة. تسمح لك بتقسيم برنامجك الكبير إلى وحدات صغيرة قابلة لإعادة الاستخدام، مما يجعل الكود أقصر وأوضح وأسهل في الصيانة والتطوير. بدلاً من تكرار نفس الأسطر عشرات المرات، تكتبها مرة واحدة في دالة وتستدعيها عند الحاجة.
في هذا الدرس المفصل، ستتعلم كيفية إنشاء الدوال في بايثون، استدعائها، إرجاع القيم منها، وفهم نطاق المتغيرات. هذا الدرس هو بوابتك نحو كتابة كود احترافي ومنظم.
1. ما هي الدوال ولماذا نحتاجها؟
الدالة (Function) هي كتلة من الكود المنظم والقابل لإعادة الاستخدام، مصممة لأداء مهمة محددة. عندما تنشئ دالة، أنت تعطي اسماً لمجموعة من الأوامر يمكنك تنفيذها في أي وقت بمجرد ذكر هذا الاسم.
فوائد استخدام الدوال
- إعادة الاستخدام (Reusability): كتابة الكود مرة واحدة واستخدامه عدة مرات
- التنظيم (Organization): تقسيم البرنامج الكبير إلى وحدات صغيرة مفهومة
- سهولة الصيانة (Maintainability): تعديل الكود في مكان واحد ينعكس في كل مكان
- سهولة القراءة (Readability): الأسماء المعبرة للدوال توضح ماذا يفعل الكود
- تقليل الأخطاء: اختبار الدالة مرة واحدة يضمن صحتها في كل استخدام
- التعاون: تسهيل العمل الجماعي بتوزيع الدوال على المبرمجين
أنواع الدوال في بايثون
| النوع | الوصف | مثال |
|---|---|---|
| الدوال المدمجة | دوال جاهزة في بايثون | print(), len(), input() |
| الدوال المعرفة من المستخدم | دوال تنشئها بنفسك | calculate_total() |
| الدوال المجهولة (Lambda) | دوال قصيرة بدون اسم | lambda x: x * 2 |
2. إنشاء دالة باستخدام def
لإنشاء دالة في بايثون، نستخدم الكلمة المفتاحية def (اختصار define) متبوعة باسم الدالة وأقواس ثم نقطتان. الكود داخل الدالة يكتب مع إزاحة للداخل.
# الصيغة العامة:
# def function_name():
# code_block
# مثال: دالة ترحيب بسيطة
def greet():
print("=" * 30)
print(" مرحباً بك في البرنامج!")
print("=" * 30)
# استدعاء الدالة (تنفيذها)
greet()
print("\nيمكنك استدعاء الدالة عدة مرات:\n")
greet()
greet()
قواعد تسمية الدوال
- يجب أن يبدأ الاسم بحرف أو شرطة سفلية (_)
- يمكن أن يحتوي على حروف وأرقام وشرطات سفلية
- لا يمكن استخدام الكلمات المحجوزة (مثل
if,for) - الأسماء حساسة لحالة الأحرف (
myFuncيختلف عنmyfunc) - يُفضل استخدام أسماء معبرة بأسلوب snake_case
calculate_average() أفضل بكثير من calc() أو ca().
3. الدوال ذات المعاملات (Parameters)
الدوال تصبح أكثر قوة عندما تستقبل بيانات من الخارج لمعالجتها. هذه البيانات تسمى المعاملات (Parameters) أو الوسائط (Arguments).
# دالة مع معامل واحد
def greet_user(name):
print(f"مرحباً يا {name}!")
print(f"سعيد بلقائك.")
# استدعاء الدالة مع قيم مختلفة
greet_user("أحمد")
print()
greet_user("سارة")
print()
# دالة مع عدة معاملات
def display_info(name, age, city):
print("-" * 35)
print(f" الاسم: {name}")
print(f" العمر: {age} سنة")
print(f" المدينة: {city}")
print("-" * 35)
display_info("محمد", 25, "القاهرة")
display_info("فاطمة", 30, "الرياض")
المعاملات الافتراضية (Default Parameters)
# تحديد قيم افتراضية للمعاملات
def greet(name, greeting="مرحباً"):
print(f"{greeting} يا {name}!")
# استدعاء بدون القيمة الافتراضية
greet("أحمد") # سيستخدم "مرحباً"
# استدعاء مع تحديد القيمة
greet("سارة", "أهلاً وسهلاً") # سيستخدم القيمة المحددة
4. إرجاع القيم باستخدام return
حتى الآن، دوالنا تطبع نتائج فقط. لكن الدوال الحقيقية غالباً تحسب قيمة وترجعها لتستخدمها في مكان آخر. هنا يأتي دور الكلمة المفتاحية return.
# دالة تحسب مربع رقم وترجع النتيجة
def square(number):
result = number ** 2
return result
# استخدام القيمة المرجعة
x = 5
squared = square(x)
print(f"مربع {x} هو {squared}")
# يمكن استخدام الدالة مباشرة في تعبيرات
print(f"مربع 7 هو {square(7)}")
print(f"مجموع مربعي 3 و 4 هو {square(3) + square(4)}")
إرجاع عدة قيم
# دالة تحسب إحصائيات قائمة أرقام
def calculate_stats(numbers):
total = sum(numbers)
count = len(numbers)
average = total / count
minimum = min(numbers)
maximum = max(numbers)
return total, count, average, minimum, maximum
# استخدام الدالة
grades = [85, 92, 78, 95, 88, 76, 90]
total, count, avg, min_val, max_val = calculate_stats(grades)
print("إحصائيات الدرجات:")
print("-" * 30)
print(f"المجموع: {total}")
print(f"العدد: {count}")
print(f"المتوسط: {avg:.2f}")
print(f"أدنى درجة: {min_val}")
print(f"أعلى درجة: {max_val}")
return تنهي تنفيذ الدالة فوراً. أي كود بعد return لن يُنفذ.
5. نطاق المتغيرات (Variable Scope)
نطاق المتغير يحدد أين يمكن الوصول لهذا المتغير في البرنامج. فهم النطاق ضروري لتجنب أخطاء شائعة ومربكة.
| النطاق | الوصف | إمكانية الوصول |
|---|---|---|
| محلي (Local) | متغير معرف داخل دالة | فقط داخل تلك الدالة |
| عام (Global) | متغير معرف خارج كل الدوال | في كل مكان في الملف |
# متغير عام (Global)
program_name = "نظام الإدارة"
def show_info():
# متغير محلي (Local)
version = "1.0"
# يمكن الوصول للمتغير العام من داخل الدالة
print(f"البرنامج: {program_name}")
print(f"الإصدار: {version}")
show_info()
# يمكن الوصول للمتغير العام هنا
print(f"\nاسم البرنامج: {program_name}")
# لكن لا يمكن الوصول للمتغير المحلي هنا
# print(version) # سيسبب خطأ!
تعديل المتغيرات العامة باستخدام global
counter = 0 # متغير عام
def increment():
global counter # الإعلان عن استخدام المتغير العام
counter += 1
print(f"العداد الآن: {counter}")
increment()
increment()
increment()
print(f"\nالقيمة النهائية: {counter}")
6. توثيق الدوال (Docstrings)
التوثيق الجيد يجعل الكود مفهوماً للآخرين ولنفسك بعد فترة. بايثون توفر طريقة رسمية لتوثيق الدوال تسمى Docstrings.
def calculate_area(length, width):
"""
تحسب مساحة المستطيل.
المعاملات:
length (float): طول المستطيل
width (float): عرض المستطيل
القيمة المرجعة:
float: مساحة المستطيل
مثال:
>>> calculate_area(5, 3)
15
"""
return length * width
# عرض التوثيق
print(calculate_area.__doc__)
# استخدام الدالة
area = calculate_area(10, 5)
print(f"\nالمساحة: {area}")
7. تطبيق عملي شامل: نظام إدارة المكتبة
لنجمع كل ما تعلمناه في تطبيق عملي متكامل يحاكي نظام إدارة مكتبة بسيط.
# نظام إدارة المكتبة
library = []
def add_book(title, author, year):
"""إضافة كتاب جديد للمكتبة"""
book = {
"title": title,
"author": author,
"year": year,
"available": True
}
library.append(book)
print(f"[+] تمت إضافة: {title}")
def display_books():
"""عرض جميع الكتب"""
print("\n" + "=" * 50)
print(" قائمة الكتب")
print("=" * 50)
if not library:
print(" المكتبة فارغة!")
return
for i, book in enumerate(library, 1):
status = "متاح" if book["available"] else "معار"
print(f"{i}. {book['title']}")
print(f" المؤلف: {book['author']} | السنة: {book['year']}")
print(f" الحالة: [{status}]")
print("-" * 50)
def search_book(keyword):
"""البحث عن كتاب"""
results = []
for book in library:
if keyword.lower() in book["title"].lower():
results.append(book)
return results
def borrow_book(title):
"""استعارة كتاب"""
for book in library:
if book["title"].lower() == title.lower():
if book["available"]:
book["available"] = False
return True, "تمت الاستعارة بنجاح"
else:
return False, "الكتاب معار حالياً"
return False, "الكتاب غير موجود"
# استخدام النظام
print("=" * 50)
print(" نظام إدارة المكتبة")
print("=" * 50)
# إضافة كتب
add_book("Python للمبتدئين", "أحمد محمد", 2023)
add_book("تعلم البرمجة", "سارة علي", 2022)
add_book("Python المتقدم", "محمد حسن", 2024)
# عرض الكتب
display_books()
# البحث
print("\nالبحث عن 'Python':")
results = search_book("Python")
for book in results:
print(f" - {book['title']}")
# استعارة
print("\nمحاولة استعارة 'Python للمبتدئين':")
success, message = borrow_book("Python للمبتدئين")
print(f" {message}")
8. أفضل الممارسات
- استخدم أسماء معبرة ووصفية
- اجعل كل دالة تؤدي مهمة واحدة
- وثق الدوال باستخدام docstrings
- استخدم return بدلاً من print حيث أمكن
- تجنب الدوال الطويلة جداً
- لا تستخدم أسماء مبهمة مثل
f() - لا تفرط في استخدام
global - لا تنسخ الكود بدلاً من إنشاء دالة
- لا تتجاهل التوثيق
- لا تضع عدداً كبيراً من المعاملات
ملخص الدرس
- الدوال تنظم الكود وتسمح بإعادة الاستخدام
- استخدم
defلإنشاء دالة - المعاملات تمرر البيانات للدالة
returnترجع قيمة من الدالة- المتغيرات المحلية موجودة فقط داخل الدالة
الخطوة التالية: تعمق أكثر في المعاملات وأنواعها المختلفة.
الخطوة التالية
تعلم المزيد عن أنواع المعاملات المختلفة في الدوال
الدرس التالي: المعاملات في الدوال (Parameters)