البرمجة
الدوال (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> → <class 'int'></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 للمبتدئين** — لتبني أول أعمالك الحقيقية!
**جرب التمارين الخمسة قبل الانتقال للمقال التالي. الممارسة هي المفتاح!**
**ما نوع الدالة التي استمتعت بكتابتها؟ شاركنا في التعليقات!**