الدوال ودوال اللامبدا
في هذا الدرس سنتعلم كيفية إنشاء الدوال لتنظيم الكود وإعادة استخدامه، وفهم المعاملات والقيم المرجعة، ونطاق المتغيرات، ودوال اللامبدا للعمليات السريعة.
📌 مقدمة عن الدوال (Functions)
الدالة هي كتلة من الكود قابلة لإعادة الاستخدام، تؤدي وظيفة محددة. بدلاً من كتابة نفس الكود عدة مرات، نكتبه مرة واحدة ونستدعيه عند الحاجة.
لماذا نستخدم الدوال؟
- تجنب التكرار: اكتب الكود مرة واحدة واستخدمه عدة مرات
- سهولة التنقيح (Debugging): عزل الأخطاء وإصلاحها بشكل أسرع
- تصميم معياري (Modular): تقسيم المشكلات الكبيرة إلى أجزاء صغيرة
- العمل الجماعي: يسمح لعدة أشخاص بالعمل بالتوازي على أجزاء مختلفة
🔧 هيكلة الدالة (Function Anatomy)
يتم تعريف الدالة باستخدام الكلمة المفتاحية def، تليها اسم الدالة، ثم المعاملات (Parameters)
بين قوسين. جسم الدالة يجب أن يكون مُزاحاً (Indented).
الفرق بين Parameter و Argument
- Parameter (المُعامل): المتغير الذي يتم تعريفه بين القوسين عند إنشاء الدالة
- Argument (القيمة الممررة): القيمة الفعلية التي يتم إرسالها للدالة عند استدعائها
أنواع المعاملات
- Positional: تعتمد على الترتيب
- Keyword: تعتمد على اسم المعامل (تمنح مرونة)
- Default: قيم افتراضية تستخدم إذا لم يقم المستخدم بإدخال قيمة
# تعريف دالة بسيطة جداً
def introduce(name, age):
print("My name is " + name + " and I am " + str(age) + " years old.")
# الاستدعاء
introduce("Ahmed", 30)
# استخدام القيم الافتراضية وتنسيق النصوص الحديث (f-string)
def introduce(name, age=30):
"""Prints a formatted introduction message."""
print(f"My name is {name} and I am {age} years old.")
# الاستدعاء بدون تمرير العمر (سيأخذ القيمة الافتراضية)
introduce(name="Ahmed")
↩️ القيم المرجعة (Return Values)
تستخدم الدالة return لإرجاع بيانات للبرنامج لاستخدامها لاحقاً. الدالة التي لا تحتوي على
return تعيد القيمة None افتراضياً. يمكن للدالة إرجاع قيم متعددة باستخدام الـ Tuples.
def area_of_circle(radius):
pi = 3.14
area = pi * (radius * radius)
print(area) # طباعة النتيجة مباشرة
area_of_circle(5)
import math
def calculate_circle_area(radius):
"""Calculates and returns the area of a circle."""
if radius < 0:
return None # التعامل مع القيم غير المنطقية
return math.pi * (radius ** 2)
# تخزين النتيجة لاستخدامها لاحقاً
area = calculate_circle_area(5)
print(f"Area: {area:.2f}")
return بدلاً من print داخل الدالة إذا كنت تريد استخدام النتيجة لاحقاً.
الدالة التي تطبع فقط لا يمكن إعادة استخدام نتيجتها!
🌍 نطاق المتغيرات (Scope & Lifetime)
يحدد النطاق (Scope) مكان رؤية المتغير والوصول إليه في الكود.
- Local Scope (محلي): متغيرات تُعرف داخل الدالة وتموت بانتهاء تنفيذها
- Global Scope (عام): متغيرات تُعرف خارج أي دالة ويمكن الوصول إليها من أي مكان
x = 10 # متغير عام (Global)
def test_scope():
x = 5 # متغير محلي (Local) - لا يؤثر على العام
print(f"Inside function: {x}")
test_scope() # سيطبع 5
print(f"Outside: {x}") # سيطبع 10
💡 قاعدة ذهبية
تجنب استخدام نفس أسماء المتغيرات في النطاق العام والمحلي لتفادي الالتباس. استخدم أسماء واضحة ومميزة لكل نطاق!
⚡ دوال اللامبدا (Lambda Functions)
هي دوال مجهولة الاسم (Anonymous)، تتكون من سطر واحد، وتستخدم للعمليات البسيطة والسريعة.
الصيغة: lambda arguments: expression
مقارنة سريعة
| Lambda | Regular Function |
|---|---|
| سطر واحد | متعددة الأسطر |
| بدون اسم | لها اسم |
| للكود البسيط | للمنطق المعقد |
numbers = [1, 2, 3, 4, 5]
squared_list = []
def square(x):
return x * x
for num in numbers:
squared_list.append(square(num))
print(squared_list)
numbers = [1, 2, 3, 4, 5]
# استخدام map مع lambda لاختصار العملية في سطر واحد
squared = list(map(lambda x: x * x, numbers))
print(squared)
استخدامات Lambda الشائعة
# Example 1: filter() مع lambda
numbers = [1, 2, 3, 4, 5, 6, 7, 8]
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(f"Even numbers: {evens}")
# Example 2: sorted() مع lambda
students = [
{"name": "Ahmed", "grade": 85},
{"name": "Sara", "grade": 92},
{"name": "Ali", "grade": 78}
]
sorted_students = sorted(students, key=lambda s: s["grade"], reverse=True)
print(f"Top student: {sorted_students[0]['name']}")
✅ أفضل الممارسات (Best Practices)
استخدم Lambda عندما:
- العملية بسيطة وقصيرة (سطر واحد)
- تحتاج دالة مؤقتة لمرة واحدة فقط
- تستخدمها مع
map()أوfilter()أوsorted()
- الكود معقد أو يحتوي على عدة جمل برمجية
- يؤثر سلباً على وضوح الكود (Readability)
- تحتاج نفس الدالة في أماكن متعددة - استخدم
defبدلاً منها
مثال: متى تستخدم def بدلاً من lambda
# Lambda معقدة وصعبة القراءة
calculate = lambda x: x * 2 if x > 10 else x * 3 if x > 5 else x * 4
result = calculate(7)
# دالة عادية واضحة وسهلة القراءة
def calculate(x):
"""Calculate value based on ranges."""
if x > 10:
return x * 2
elif x > 5:
return x * 3
else:
return x * 4
result = calculate(7)