*args - الوسيطات الموضعية المتغيرة
*args يسمح للدالة بقبول أي عدد من الوسيطات الموضعية.
تُجمع الوسيطات في صف (tuple).
# *args تجمع الوسيطات الموضعية الإضافية
def مجموع_الكل(*args):
"""جمع أي عدد من الوسيطات."""
print(f"نوع args: {type(args)}") # tuple
return sum(args)
print(مجموع_الكل(1, 2)) # 3
print(مجموع_الكل(1, 2, 3, 4, 5)) # 15
print(مجموع_الكل()) # 0
# دمج معامل عادي مع *args
def تحية_الجميع(التحية, *الأسماء):
for اسم in الأسماء:
print(f"{التحية} يا {اسم}!")
تحية_الجميع("مرحباً", "أحمد", "سارة", "محمد")
# مرحباً يا أحمد!
# مرحباً يا سارة!
# مرحباً يا محمد!
# *args مع معاملات أخرى
def وصف_حيوان(الحيوان, *الصفات, المالك="غير معروف"):
print(f"الحيوان: {الحيوان}")
print(f"الصفات: {', '.join(الصفات)}")
print(f"المالك: {المالك}")
وصف_حيوان("قطة", "لطيفة", "ودودة", "نشيطة", المالك="سارة")
**kwargs - الوسيطات المُسماة المتغيرة
**kwargs يسمح للدالة بقبول أي عدد من الوسيطات المُسماة.
تُجمع الوسيطات في قاموس.
# **kwargs تجمع الوسيطات المُسماة الإضافية
def طباعة_معلومات(**kwargs):
"""طباعة جميع الوسيطات المُسماة."""
print(f"نوع kwargs: {type(kwargs)}") # dict
for مفتاح, قيمة in kwargs.items():
print(f"{مفتاح}: {قيمة}")
طباعة_معلومات(الاسم="أحمد", العمر=30, المدينة="القاهرة")
# الاسم: أحمد
# العمر: 30
# المدينة: القاهرة
# إنشاء كائنات مع kwargs
def إنشاء_شخص(**kwargs):
return {
"الاسم": kwargs.get("الاسم", "غير معروف"),
"العمر": kwargs.get("العمر", 0),
"البريد": kwargs.get("البريد", "غير متاح")
}
شخص = إنشاء_شخص(الاسم="سارة", العمر=25)
print(شخص) # {'الاسم': 'سارة', 'العمر': 25, 'البريد': 'غير متاح'}
# دمج جميع أنواع المعاملات
def دالة_معقدة(مطلوب, *args, افتراضي="قيمة", **kwargs):
print(f"المطلوب: {مطلوب}")
print(f"Args: {args}")
print(f"الافتراضي: {افتراضي}")
print(f"Kwargs: {kwargs}")
دالة_معقدة("الأول", 1, 2, 3, افتراضي="مخصص", س=10, ص=20)
تفريغ الوسيطات
# تفريغ قائمة/صف مع *
def جمع(أ, ب, ج):
return أ + ب + ج
أرقام = [1, 2, 3]
print(جمع(*أرقام)) # 6 (يفرغ القائمة)
# تفريغ قاموس مع **
def تحية(الاسم, رسالة_ترحيب="مرحباً"):
print(f"{رسالة_ترحيب} يا {الاسم}!")
شخص = {"الاسم": "أحمد", "رسالة_ترحيب": "أهلاً"}
تحية(**شخص) # أهلاً يا أحمد!
# دمج التفريغ
def ملف_كامل(الأول, الأخير, *الهوايات, **التفاصيل):
print(f"الاسم: {الأول} {الأخير}")
print(f"الهوايات: {', '.join(الهوايات)}")
for مفتاح, قيمة in التفاصيل.items():
print(f"{مفتاح}: {قيمة}")
الأسماء = ["محمد", "علي"]
الهوايات = ["القراءة", "البرمجة", "الألعاب"]
المعلومات = {"العمر": 30, "المدينة": "الرياض"}
ملف_كامل(*الأسماء, *الهوايات, **المعلومات)
دوال Lambda
دوال Lambda هي دوال صغيرة مجهولة الاسم تُعرَّف في سطر واحد. مفيدة للعمليات القصيرة والبسيطة.
# صيغة lambda الأساسية: lambda الوسيطات: التعبير
# دالة عادية
def تربيع(س):
return س ** 2
# دالة lambda مكافئة
تربيع = lambda س: س ** 2
print(تربيع(5)) # 25
# وسيطات متعددة
جمع = lambda أ, ب: أ + ب
print(جمع(3, 4)) # 7
# استخدام شائع: الترتيب
الطلاب = [
{"الاسم": "أحمد", "الدرجة": 90},
{"الاسم": "سارة", "الدرجة": 85},
{"الاسم": "محمد", "الدرجة": 95}
]
# ترتيب حسب الدرجة
مرتب_بالدرجة = sorted(الطلاب, key=lambda ط: ط["الدرجة"])
print([ط["الاسم"] for ط in مرتب_بالدرجة]) # ['سارة', 'أحمد', 'محمد']
# ترتيب حسب الاسم
مرتب_بالاسم = sorted(الطلاب, key=lambda ط: ط["الاسم"])
# ترتيب تنازلي
مرتب_تنازلي = sorted(الطلاب, key=lambda ط: ط["الدرجة"], reverse=True)
# Lambda مع filter
الأرقام = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
الزوجية = list(filter(lambda س: س % 2 == 0, الأرقام))
print(الزوجية) # [2, 4, 6, 8, 10]
# Lambda مع map
المربعات = list(map(lambda س: س ** 2, الأرقام))
print(المربعات) # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
استخدم lambda لـ:
- دوال قصيرة من تعبير واحد
- دوال تُمرر إلى
sorted()،filter()،map() - دوال الاستدعاء البسيطة
استخدم الدوال العادية لـ:
- منطق معقد أو عبارات متعددة
- دوال تحتاج نصوص توثيقية
- دوال قابلة لإعادة الاستخدام في أماكن متعددة
الدوال عالية المستوى
دوال تأخذ دوالاً أخرى كوسيطات أو تُرجع دوالاً.
# map() - تطبيق دالة على كل عنصر
الأرقام = [1, 2, 3, 4, 5]
def مضاعفة(س):
return س * 2
المضاعف = list(map(مضاعفة, الأرقام))
print(المضاعف) # [2, 4, 6, 8, 10]
# filter() - الاحتفاظ بالعناصر التي تجتاز الاختبار
def هل_زوجي(س):
return س % 2 == 0
الزوجية = list(filter(هل_زوجي, الأرقام))
print(الزوجية) # [2, 4]
# reduce() - عملية تراكمية
from functools import reduce
def جمع(أ, ب):
return أ + ب
المجموع = reduce(جمع, الأرقام) # ((((1+2)+3)+4)+5)
print(المجموع) # 15
# مع lambda
الحاصل = reduce(lambda أ, ب: أ * ب, الأرقام)
print(الحاصل) # 120
# دالة عالية المستوى مخصصة
def تطبيق_عملية(الأرقام, العملية):
"""تطبيق العملية على كل رقم."""
return [العملية(ن) for ن in الأرقام]
الناتج = تطبيق_عملية([1, 2, 3], lambda س: س ** 2)
print(الناتج) # [1, 4, 9]
# دالة تُرجع دالة
def منشئ_المضاعف(ن):
"""إنشاء دالة تضرب في ن."""
def المضاعف(س):
return س * ن
return المضاعف
مضاعفة = منشئ_المضاعف(2)
ثلاثة_أضعاف = منشئ_المضاعف(3)
print(مضاعفة(5)) # 10
print(ثلاثة_أضعاف(5)) # 15
الإغلاقات (Closures)
الإغلاق هو دالة تتذكر القيم من نطاقها المحيط.
# مثال على الإغلاق
def منشئ_العداد():
العدد = 0 # متغير محاط
def العداد():
nonlocal العدد # الوصول للنطاق المحيط
العدد += 1
return العدد
return العداد
# كل استدعاء لـ منشئ_العداد ينشئ إغلاقاً جديداً
عداد1 = منشئ_العداد()
عداد2 = منشئ_العداد()
print(عداد1()) # 1
print(عداد1()) # 2
print(عداد1()) # 3
print(عداد2()) # 1 (عداد مستقل)
print(عداد2()) # 2
# إغلاق عملي: مسجل قابل للتخصيص
def منشئ_المسجل(البادئة):
def تسجيل(الرسالة):
print(f"[{البادئة}] {الرسالة}")
return تسجيل
مسجل_الأخطاء = منشئ_المسجل("خطأ")
مسجل_المعلومات = منشئ_المسجل("معلومات")
مسجل_الأخطاء("حدث خطأ ما!") # [خطأ] حدث خطأ ما!
مسجل_المعلومات("بدأت العملية") # [معلومات] بدأت العملية
# إغلاق مع حالة متغيرة
def منشئ_المراكم():
المجموع = [0] # استخدام قائمة للسماح بالتعديل
def إضافة(القيمة):
المجموع[0] += القيمة
return المجموع[0]
return إضافة
مراكم = منشئ_المراكم()
print(مراكم(10)) # 10
print(مراكم(5)) # 15
print(مراكم(3)) # 18
التكرار الذاتي (Recursion)
دالة تستدعي نفسها لحل مشاكل فرعية أصغر.
# المضروب: ن! = ن * (ن-1) * (ن-2) * ... * 1
def مضروب(ن):
if ن <= 1: # الحالة الأساسية
return 1
return ن * مضروب(ن - 1) # الحالة التكرارية
print(مضروب(5)) # 120 (5 * 4 * 3 * 2 * 1)
# متتالية فيبوناتشي
def فيبوناتشي(ن):
if ن <= 1:
return ن
return فيبوناتشي(ن - 1) + فيبوناتشي(ن - 2)
print([فيبوناتشي(i) for i in range(10)])
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
# جمع القائمة (تكراري)
def مجموع_القائمة(القائمة):
if not القائمة: # الحالة الأساسية: قائمة فارغة
return 0
return القائمة[0] + مجموع_القائمة(القائمة[1:])
print(مجموع_القائمة([1, 2, 3, 4, 5])) # 15
# تسطيح القائمة المتداخلة
def تسطيح(القائمة):
الناتج = []
for عنصر in القائمة:
if isinstance(عنصر, list):
الناتج.extend(تسطيح(عنصر)) # استدعاء تكراري
else:
الناتج.append(عنصر)
return الناتج
متداخلة = [1, [2, 3, [4, 5]], 6, [7, [8, 9]]]
print(تسطيح(متداخلة)) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
بايثون لديها حد افتراضي للتكرار (عادة 1000). للتكرار العميق، فكر في التكرار الحلقي أو زيادة الحد:
import sys
sys.setrecursionlimit(10000) # زيادة الحد
# أفضل: استخدم التكرار الحلقي للتكرار العميق
def مضروب_حلقي(ن):
الناتج = 1
for i in range(2, ن + 1):
الناتج *= i
return الناتج
🎯 تحدي: معالج بيانات مرن
أنشئ دالة تعالج البيانات مع عمليات قابلة للتخصيص:
- تقبل بيانات وأي عدد من دوال المعالجة
- تطبق كل دالة بالترتيب
- تُرجع النتيجة النهائية
💡 عرض الحل
def معالجة_بيانات(البيانات, *المعالجات):
"""
تطبيق دوال معالجة متعددة على البيانات بالتسلسل.
الوسيطات:
البيانات: البيانات المبدئية للمعالجة
*المعالجات: الدوال المراد تطبيقها بالترتيب
الإرجاع:
البيانات المعالجة بعد جميع التحويلات
"""
الناتج = البيانات
for معالج in المعالجات:
الناتج = معالج(الناتج)
return الناتج
# مثال على المعالجات
def إزالة_المسافات(نص):
return نص.replace(" ", "")
def إلى_أحرف_كبيرة(نص):
return نص.upper()
def إضافة_بادئة(نص):
return f"النتيجة: {نص}"
# استخدام المعالج
النص = "hello world"
الناتج = معالجة_بيانات(النص, إزالة_المسافات, إلى_أحرف_كبيرة, إضافة_بادئة)
print(الناتج) # النتيجة: HELLOWORLD
# معالجة الأرقام
الأرقام = [1, 2, 3, 4, 5]
الناتج = معالجة_بيانات(
الأرقام,
lambda س: [ن * 2 for ن in س], # مضاعفة
lambda س: [ن for ن in س if ن > 4], # تصفية > 4
sum # جمع
)
print(الناتج) # 24 (6 + 8 + 10)
🎯 تحدي: نظام معالجة الأحداث
أنشئ نظام أحداث بسيط يمكنه:
- تسجيل معالجات للأحداث
- إطلاق أحداث مع بيانات
- استدعاء جميع المعالجات لذلك الحدث
💡 عرض الحل
def منشئ_نظام_الأحداث():
"""إنشاء نظام معالجة أحداث باستخدام الإغلاقات."""
المعالجات = {}
def عند(اسم_الحدث, المعالج):
"""تسجيل معالج لحدث."""
if اسم_الحدث not in المعالجات:
المعالجات[اسم_الحدث] = []
المعالجات[اسم_الحدث].append(المعالج)
def إطلاق(اسم_الحدث, *args, **kwargs):
"""إطلاق حدث، استدعاء جميع المعالجات المسجلة."""
if اسم_الحدث in المعالجات:
for معالج in المعالجات[اسم_الحدث]:
معالج(*args, **kwargs)
def إيقاف(اسم_الحدث, المعالج=None):
"""إزالة معالج(ات) لحدث."""
if المعالج is None:
المعالجات.pop(اسم_الحدث, None)
elif اسم_الحدث in المعالجات:
المعالجات[اسم_الحدث].remove(المعالج)
return عند, إطلاق, إيقاف
# إنشاء نظام الأحداث
عند, إطلاق, إيقاف = منشئ_نظام_الأحداث()
# تسجيل المعالجات
def تسجيل_الدخول(المستخدم):
print(f"المستخدم سجل دخوله: {المستخدم}")
def إرسال_ترحيب(المستخدم):
print(f"تم إرسال رسالة ترحيب إلى {المستخدم}")
def تحديث_الإحصائيات(المستخدم):
print(f"تم تحديث الإحصائيات لـ {المستخدم}")
عند("تسجيل_دخول_مستخدم", تسجيل_الدخول)
عند("تسجيل_دخول_مستخدم", إرسال_ترحيب)
عند("تسجيل_دخول_مستخدم", تحديث_الإحصائيات)
# إطلاق الحدث
print("--- المستخدم يسجل الدخول ---")
إطلاق("تسجيل_دخول_مستخدم", "ahmed@example.com")
# إزالة معالج واحد
إيقاف("تسجيل_دخول_مستخدم", إرسال_ترحيب)
print("\n--- تسجيل دخول آخر ---")
إطلاق("تسجيل_دخول_مستخدم", "sara@example.com")
📝 ملخص الدرس
*argsيجمع الوسيطات الموضعية في صف**kwargsيجمع الوسيطات المُسماة في قاموس- Lambda:
lambda س: تعبيرلدوال بسيطة - الدوال عالية المستوى:
map()،filter()،reduce() - الإغلاقات تتذكر المتغيرات من النطاق المحيط
- استخدم
nonlocalلتعديل المتغيرات المحيطة - التكرار الذاتي يحتاج حالة أساسية لمنع الحلقات اللانهائية