البرمجة

الدوال (Functions) في Python — نظّم كودك باحتراف

📅 2026-09-23⏱ 12 دقائق قراءة
حتى الآن، كل كود كتبناه كان يسير في خط مستقيم: من الأعلى للأسفل. لكن البرامج الحقيقية تحتاج إلى **تنظيم** — تقسيم الكود إلى مهام صغيرة قابلة لإعادة الاستخدام. هنا يأتي دور **الدوال (Functions)** — التي تحوّل كودك من فوضى إلى هيكل منظم وقابل للتوسع. بنهاية هذا المقال، ستكون قادراً على: - تعريف دوالك الخاصة باستخدام `def` - تمرير المعاملات (Parameters) واستقبال الوسائط (Arguments) - إرجاع القيم (Return) من الدوال - فهم نطاق المتغيرات (Scope) - استخدام الدوال المجهولة (Lambda) - بناء مشاريع منظمة باستخدام الدوال ## 1. ما هي الدوال ولماذا نحتاجها؟ ### التعريف **الدالة (Function)** هي كتلة من الكود لها اسم محدد، تؤدي مهمة معينة، ويمكن استدعاؤها عدة مرات. ### القياس العملي تخيل أنك في مطعم. بدلاً من أن تشرح للطاهي كل خطوة لإعداد الطبق، تقول فقط: "أريد بيتزا". الطاهي يعرف ما يجب فعله. **الدالة هي مثل الطاهي** — تعطيها "الطلب" (المعاملات)، وتعيد لك "الطبق" (القيمة المُرجعة). ### المشكلة: كود مكرر ```python # بدون دوال — كود مكرر name1 = "أحمد" print(f"مرحباً {name1}!") print(f"أهلاً بك في الموقع") print() name2 = "سارة" print(f"مرحباً {name2}!") print(f"أهلاً بك في الموقع") print() name3 = "محمد" print(f"مرحباً {name3}!") print(f"أهلاً بك في الموقع") ``` **المشكلة:** نفس الكود مكرر 3 مرات! ### الحل: استخدام دالة ```python # مع دالة — كود نظيف def welcome(name): print(f"مرحباً {name}!") print(f"أهلاً بك في الموقع") print() welcome("أحمد") welcome("سارة") welcome("محمد") ``` **النتيجة:** نفس النتيجة بكود أقل وأنظف! ### فوائد الدوال <table> <thead> <tr> <th>الفائدة</th> <th>الشرح</th> </tr> </thead> <tbody> <tr> <td><strong>إعادة الاستخدام</strong></td> <td>اكتب مرة، استخدم مرات لا نهائية</td> </tr> <tr> <td><strong>تنظيم الكود</strong></td> <td>كل دالة لها مهمة واحدة واضحة</td> </tr> <tr> <td><strong>سهولة الصيانة</strong></td> <td>تعديل واحد يؤثر على كل الاستخدامات</td> </tr> <tr> <td><strong>سهولة الاختبار</strong></td> <td>يمكن اختبار كل دالة على حدة</td> </tr> <tr> <td><strong>قراءة أفضل</strong></td> <td>الكود يشرح نفسه بأسماء الدوال</td> </tr> </tbody> </table> ## 2. تعريف الدوال باستخدام def ### الصيغة الأساسية ```python def اسم_الدالة(): # الكود الذي تنفذه الدالة ``` **⚠️ ملاحظات مهمة:** - تبدأ الكلمة المفتاحية `def` (اختصار define) - اسم الدالة يتبع نفس قواعد أسماء المتغيرات - تنتهي بنقطتين `:` - الكود داخلها مُزاح (Indented) ### أول دالة لك ```python def greet(): print("مرحباً بك!") print("أهلاً وسهلاً") # استدعاء الدالة greet() greet() ``` **النتيجة:** ``` مرحباً بك! أهلاً وسهلاً مرحباً بك! أهلاً وسهلاً ``` ### ⚠️ ملاحظة مهمة: تعريف مقابل استدعاء ```python # هذا تعريف — لا ينفذ أي شيء بعد def greet(): print("مرحباً") # هذا استدعاء — هنا يُنفذ الكود greet() ``` **القاعدة:** تعريف الدالة لا ينفذ شيئاً. يجب **استدعاؤها** بالاسم مع `()`. ### دالة بدون معاملات ```python def show_menu(): print("=" * 30) print("📋 قائمة المطعم") print("=" * 30) print("1. بيتزا") print("2. برجر") print("3. شاورما") print("=" * 30) show_menu() ``` **النتيجة:** ``` ============================== 📋 قائمة المطعم ============================== 1. بيتزا 2. برجر 3. شاورما ============================== ``` ## 3. المعاملات (Parameters) والوسائط (Arguments) ### الفرق بينهما <table> <thead> <tr> <th>المصطلح</th> <th>المعنى</th> <th>المثال</th> </tr> </thead> <tbody> <tr> <td><strong>Parameter (معامل)</strong></td> <td>المتغير في تعريف الدالة</td> <td><code>def greet(name):</code></td> </tr> <tr> <td><strong>Argument (وسيط)</strong></td> <td>القيمة المرسلة عند الاستدعاء</td> <td><code>greet("أحمد")</code></td> </tr> </tbody> </table> ### دالة بمعامل واحد ```python def greet(name): print(f"مرحباً {name}!") greet("أحمد") greet("سارة") greet("محمد") ``` **النتيجة:** ``` مرحباً أحمد! مرحباً سارة! مرحباً محمد! ``` ### دالة بعدة معاملات ```python def introduce(name, age, city): print(f"اسمي {name}") print(f"عمري {age} سنة") print(f"أسكن في {city}") print("-" * 20) introduce("أحمد", 25, "عمّان") introduce("سارة", 30, "دبي") ``` **النتيجة:** ``` اسمي أحمد عمري 25 سنة أسكن في عمّان -------------------- اسمي سارة عمري 30 سنة أسكن في دبي -------------------- ``` ### ⚠️ عدد الوسائط يجب أن يطابق ```python def greet(name): print(f"مرحباً {name}!") # خطأ — دالة تتوقع معاملاً واحداً greet() # TypeError greet("أحمد", "محمد") # TypeError ``` **الخطأ:** `TypeError: greet() missing 1 required positional argument` ## 4. أنواع المعاملات ### 1. معاملات افتراضية (Default Parameters) ```python def greet(name, greeting="مرحباً"): print(f"{greeting} {name}!") greet("أحمد") greet("سارة", "أهلاً") greet("محمد", "صباح الخير") ``` **النتيجة:** ``` مرحباً أحمد! أهلاً سارة! صباح الخير محمد! ``` **القاعدة:** المعاملات الافتراضية تأتي **في نهاية** القائمة. ```python # خطأ — المعامل الافتراضي قبل الإلزامي def greet(greeting="مرحباً", name): # SyntaxError print(f"{greeting} {name}") # صحيح def greet(name, greeting="مرحباً"): print(f"{greeting} {name}") ``` ### 2. معاملات بالاسم (Keyword Arguments) ```python def introduce(name, age, city): print(f"{name}، {age} سنة، من {city}") # بدون أسماء — يجب الترتيب introduce("أحمد", 25, "عمّان") # بالأسماء — الترتيب حر introduce(age=25, city="عمّان", name="أحمد") ``` **النتيجة:** كلاهما يعطي نفس النتيجة. **الفائدة:** الكود أوضح، لا حاجة لتذكر الترتيب. ### 3. عدد متغير من المعاملات (*args) ```python def sum_all(*numbers): total = 0 for num in numbers: total += num return total print(sum_all(1, 2, 3)) print(sum_all(10, 20, 30, 40, 50)) ``` **النتيجة:** ``` 6 150 ``` **شرح:** `*numbers` يستقبل أي عدد من الوسائط كـ tuple. ### 4. معاملات مسماة متغيرة (**kwargs) ```python def print_info(**info): for key, value in info.items(): print(f"{key}: {value}") print_info(name="أحمد", age=25, city="عمّان") ``` **النتيجة:** ``` name: أحمد age: 25 city: عمّان ``` **شرح:** `**info` يستقبل أي عدد من الوسائط المسماة كـ dictionary. ## 5. القيم المُرجعة (Return) ### ما هي return؟ `return` تُنهي الدالة وتُرجع قيمة للمُستدعي. ### دالة بدون return ```python def add(a, b): print(a + b) result = add(3, 5) print(f"النتيجة: {result}") ``` **النتيجة:** ``` 8 النتيجة: None ``` **لاحظ:** `result` يساوي `None` — لأن الدالة لا ترجع شيئاً. ### دالة مع return ```python def add(a, b): return a + b result = add(3, 5) print(f"النتيجة: {result}") ``` **النتيجة:** ``` النتيجة: 8 ``` ### الفرق بين print و return <table> <thead> <tr> <th>العنصر</th> <th>print</th> <th>return</th> </tr> </thead> <tbody> <tr> <td><strong>الوظيفة</strong></td> <td>يعرض على الشاشة</td> <td>يُرجع قيمة للمُستدعي</td> </tr> <tr> <td><strong>يمكن استخدامها؟</strong></td> <td>لا — فقط عرض</td> <td>نعم — في عمليات أخرى</td> </tr> <tr> <td><strong>مثال</strong></td> <td><code>print(5+3)</code> → 8</td> <td><code>return 5+3</code> → قيمة 8</td> </tr> <tr> <td><strong>الاستخدام</strong></td> <td>للعرض النهائي</td> <td>للحسابات والمنطق</td> </tr> </tbody> </table> ### إرجاع قيم متعددة ```python def calculate(a, b): total = a + b difference = a - b product = a * b return total, difference, product t, d, p = calculate(10, 3) print(f"المجموع: {t}") print(f"الفرق: {d}") print(f"الضرب: {p}") ``` **النتيجة:** ``` المجموع: 13 الفرق: 7 الضرب: 30 ``` **ملاحظة:** Python ترجع القيم كـ tuple. ### return تُنهي الدالة ```python def check_age(age): if age < 0: return "عمر غير صالح" if age < 18: return "قاصر" return "بالغ" print(check_age(-5)) print(check_age(15)) print(check_age(25)) ``` **النتيجة:** ``` عمر غير صالح قاصر بالغ ``` **مهم:** بعد `return`، لا ينفذ أي كود في الدالة. ```python def test(): print("هذا يُنفذ") return "القيمة" print("هذا لن يُنفذ أبداً") print(test()) ``` **النتيجة:** ``` هذا يُنفذ القيمة ``` ## 6. نطاق المتغيرات (Variable Scope) ### المتغيرات المحلية (Local) ```python def my_function(): x = 10 # متغير محلي print(x) my_function() print(x) # خطأ! ``` **الخطأ:** `NameError: name 'x' is not defined` **السبب:** `x` موجود فقط داخل الدالة. ### المتغيرات العامة (Global) ```python x = 10 # متغير عام def my_function(): print(x) # يمكن قراءته my_function() # النتيجة: 10 print(x) # النتيجة: 10 ``` ### الفرق بين القراءة والتعديل ```python counter = 0 def increment(): global counter # يجب استخدام global للتعديل counter += 1 increment() increment() print(counter) ``` **النتيجة:** ``` 2 ``` **⚠️ تحذير:** استخدام `global` غير مُفضل — يسبب مشاكل في المشاريع الكبيرة. ### القاعدة الذهبية > **مرر ما تحتاجه، وأرجع ما تنتجه. لا تستخدم global.** ```python # ❌ سيء counter = 0 def increment(): global counter counter += 1 # ✅ جيد def increment(counter): return counter + 1 counter = 0 counter = increment(counter) counter = increment(counter) print(counter) # النتيجة: 2 ``` ## 7. الدوال المدمجة (Built-in Functions) Python تأتي مع عشرات الدوال الجاهزة: <table> <thead> <tr> <th>الدالة</th> <th>الوظيفة</th> <th>مثال</th> </tr> </thead> <tbody> <tr> <td><code>len()</code></td> <td>طول العنصر</td> <td><code>len("Python")</code> → 6</td> </tr> <tr> <td><code>max()</code></td> <td>أكبر قيمة</td> <td><code>max(1, 5, 3)</code> → 5</td> </tr> <tr> <td><code>min()</code></td> <td>أصغر قيمة</td> <td><code>min(1, 5, 3)</code> → 1</td> </tr> <tr> <td><code>sum()</code></td> <td>مجموع العناصر</td> <td><code>sum([1,2,3])</code> → 6</td> </tr> <tr> <td><code>abs()</code></td> <td>القيمة المطلقة</td> <td><code>abs(-5)</code> → 5</td> </tr> <tr> <td><code>round()</code></td> <td>التقريب</td> <td><code>round(3.7)</code> → 4</td> </tr> <tr> <td><code>sorted()</code></td> <td>ترتيب</td> <td><code>sorted([3,1,2])</code> → [1,2,3]</td> </tr> <tr> <td><code>type()</code></td> <td>نوع العنصر</td> <td><code>type(5)</code> → &lt;class 'int'&gt;</td> </tr> </tbody> </table> ## 8. الدوال المجهولة (Lambda) ### ما هي Lambda؟ `lambda` هي طريقة مختصرة لكتابة دالة صغيرة في سطر واحد. ### الصيغة ```python lambda parameters: expression ``` ### مثال مقارنة **الدالة العادية:** ```python def add(a, b): return a + b print(add(3, 5)) ``` **الدالة المجهولة:** ```python add = lambda a, b: a + b print(add(3, 5)) ``` **النتيجة:** كلاهما يعطي 8. ### متى تستخدم lambda؟ **استخدمها عندما:** - الدالة بسيطة جداً (سطر واحد) - ستُستخدم مرة واحدة فقط - مع `sorted()` أو `map()` أو `filter()` **مثال عملي:** ```python # ترتيب أسماء حسب الطول names = ["أحمد", "محمد عبد الرحمن", "سارة", "خالد إبراهيم"] # بدون lambda def get_length(name): return len(name) sorted_names = sorted(names, key=get_length) print(sorted_names) # مع lambda (أنظف) sorted_names = sorted(names, key=lambda n: len(n)) print(sorted_names) ``` ## 9. Docstrings — توثيق الدوال ### ما هي Docstring؟ نص توضيحي داخل الدالة يشرح وظيفتها. يُكتب بين ثلاث علامات تنصيص. ```python def calculate_area(length, width): """ تحسب مساحة المستطيل. المعاملات: length (float): الطول width (float): العرض العائد: float: مساحة المستطيل """ return length * width # يمكن عرض التوثيق print(calculate_area.__doc__) ``` **فائدة:** يمكنك قراءة التوثيق بـ `help()` أو `.__doc__`. ## 10. مشاريع عملية ### المشروع 1: آلة حاسبة باستخدام الدوال ```python # آلة حاسبة منظمة باستخدام الدوال def add(a, b): """جمع رقمين""" return a + b def subtract(a, b): """طرح رقمين""" return a - b def multiply(a, b): """ضرب رقمين""" return a * b def divide(a, b): """قسمة رقمين""" if b == 0: return "❌ لا يمكن القسمة على صفر" return a / b def show_menu(): """عرض القائمة""" print("\n" + "=" * 30) print("🧮 آلة حاسبة") print("=" * 30) print("1. جمع") print("2. طرح") print("3. ضرب") print("4. قسمة") print("5. خروج") print("=" * 30) def calculator(): """الدالة الرئيسية للآلة الحاسبة""" while True: show_menu() choice = input("اختر العملية (1-5): ") if choice == "5": print("👋 وداعاً!") break if choice not in ["1", "2", "3", "4"]: print("❌ اختيار غير صحيح") continue try: a = float(input("الرقم الأول: ")) b = float(input("الرقم الثاني: ")) except ValueError: print("❌ يرجى إدخال أرقام صحيحة") continue if choice == "1": print(f"النتيجة: {add(a, b)}") elif choice == "2": print(f"النتيجة: {subtract(a, b)}") elif choice == "3": print(f"النتيجة: {multiply(a, b)}") elif choice == "4": print(f"النتيجة: {divide(a, b)}") # تشغيل الآلة الحاسبة calculator() ``` ### المشروع 2: نظام إدارة المهام ```python # نظام إدارة مهام منظم بالدوال tasks = [] def add_task(title): """إضافة مهمة جديدة""" task = {"title": title, "done": False} tasks.append(task) print(f"✅ تمت إضافة: {title}") def list_tasks(): """عرض جميع المهام""" if not tasks: print("📭 لا توجد مهام") return print("\n📋 قائمة المهام:") print("-" * 40) for i, task in enumerate(tasks, 1): status = "✅" if task["done"] else "⏳" print(f"{i}. {status} {task['title']}") print("-" * 40) def complete_task(index): """إكمال مهمة""" if 1 <= index <= len(tasks): tasks[index - 1]["done"] = True print(f"🎉 تم إكمال: {tasks[index - 1]['title']}") else: print("❌ رقم المهمة غير صحيح") def delete_task(index): """حذف مهمة""" if 1 <= index <= len(tasks): removed = tasks.pop(index - 1) print(f"🗑️ تم حذف: {removed['title']}") else: print("❌ رقم المهمة غير صحيح") # تجربة النظام add_task("تعلم Python") add_task("بناء مشروع") add_task("قراءة كتاب") list_tasks() complete_task(1) list_tasks() ``` ### المشروع 3: مكتبة حسابات رياضية ```python # مكتبة حسابات رياضية باستخدام الدوال def square(n): """مربع الرقم""" return n ** 2 def cube(n): """مكعب الرقم""" return n ** 3 def is_even(n): """هل الرقم زوجي؟""" return n % 2 == 0 def is_prime(n): """هل الرقم أولي؟""" if n < 2: return False for i in range(2, int(n ** 0.5) + 1): if n % i == 0: return False return True def factorial(n): """مضروب الرقم""" if n < 0: return None result = 1 for i in range(1, n + 1): result *= i return result # اختبار الدوال print(f"مربع 5: {square(5)}") print(f"مكعب 3: {cube(3)}") print(f"هل 4 زوجي؟ {is_even(4)}") print(f"هل 7 أولي؟ {is_prime(7)}") print(f"مضروب 5: {factorial(5)}") ``` ## 11. أخطاء شائعة ### الخطأ 1: نسيان الأقواس عند الاستدعاء ```python def greet(): print("مرحباً") # خطأ — لا ينفذ الدالة greet # صحيح greet() ``` ### الخطأ 2: نسيان return ```python # خطأ def add(a, b): result = a + b # نسيت return print(add(3, 5)) # None # صحيح def add(a, b): return a + b ``` ### الخطأ 3: استخدام متغير محلي خارج الدالة ```python def calculate(): x = 10 calculate() print(x) # NameError ``` ### الخطأ 4: ترتيب خاطئ للمعاملات الافتراضية ```python # خطأ def greet(greeting="مرحباً", name): print(f"{greeting} {name}") # صحيح def greet(name, greeting="مرحباً"): print(f"{greeting} {name}") ``` ### الخطأ 5: تعديل قائمة افتراضية ```python # خطأ — القائمة الافتراضية تُنشأ مرة واحدة فقط! def add_item(item, items=[]): items.append(item) return items print(add_item("أ")) # ['أ'] print(add_item("ب")) # ['أ', 'ب'] — مشكلة! # صحيح def add_item(item, items=None): if items is None: items = [] items.append(item) return items ``` ## 12. تمارين عملية ### التمرين 1: دالة المساحة اكتب دالة `circle_area(radius)` تحسب مساحة الدائرة (π × r²). ### التمرين 2: دالة الترحيب اكتب دالة `welcome(name, time)` تطبع: - "صباح الخير [الاسم]" إذا كان `time` = "morning" - "مساء الخير [الاسم]" إذا كان `time` = "evening" ### التمرين 3: دالة الأكبر اكتب دالة `find_max(numbers)` تأخذ قائمة وتُرجع أكبر رقم. ### التمرين 4: دالة التصفية اكتب دالة `filter_even(numbers)` تُرجع قائمة بالأرقام الزوجية فقط. ### التمرين 5: دالة الحساب المتكامل اكتب دالة `calculate_grade(score)` تُرجع: - 90+ : "ممتاز" - 80-89 : "جيد جداً" - 70-79 : "جيد" - 60-69 : "مقبول" - أقل من 60 : "راسب" ## قائمة تحقق — هل تعلمت؟ <table> <thead> <tr> <th>المهارة</th> <th>الحالة</th> </tr> </thead> <tbody> <tr> <td>تعريف الدوال باستخدام <code>def</code></td> <td>⬜</td> </tr> <tr> <td>تمرير المعاملات واستقبال الوسائط</td> <td>⬜</td> </tr> <tr> <td>استخدام المعاملات الافتراضية</td> <td>⬜</td> </tr> <tr> <td>إرجاع القيم باستخدام <code>return</code></td> <td>⬜</td> </tr> <tr> <td>فهم نطاق المتغيرات (Local / Global)</td> <td>⬜</td> </tr> <tr> <td>استخدام <code>*args</code> و <code>**kwargs</code></td> <td>⬜</td> </tr> <tr> <td>كتابة الدوال المجهولة (Lambda)</td> <td>⬜</td> </tr> <tr> <td>كتابة Docstrings للتوثيق</td> <td>⬜</td> </tr> <tr> <td>بناء مشاريع منظمة بالدوال</td> <td>⬜</td> </tr> </tbody> </table> ## الخلاصة في هذا المقال، تعلمت: 1. **تعريف الدوال** — باستخدام `def` 2. **المعاملات والوسائط** — تمرير البيانات للدوال 3. **القيم المُرجعة** — إرجاع النتائج بـ `return` 4. **نطاق المتغيرات** — Local و Global 5. **الدوال المدمجة** — الجاهزة في Python 6. **الدوال المجهولة (Lambda)** — للدوال القصيرة 7. **Docstrings** — توثيق الدوال 8. **المشاريع** — تطبيق كل ما تعلمته **الدوال هي حجر الأساس للبرمجة الاحترافية** — بدونها، مشاريعك ستبقى فوضى صغيرة. **في المقال القادم:** سنتطبق كل ما تعلمناه في **5 مشاريع Python للمبتدئين** — لتبني أول أعمالك الحقيقية! **جرب التمارين الخمسة قبل الانتقال للمقال التالي. الممارسة هي المفتاح!** **ما نوع الدالة التي استمتعت بكتابتها؟ شاركنا في التعليقات!**