✨ الديكورات في بايثون: سحر تعديل الدوال دون لمس كودها!
مرحباً بك في عالم الديكورات (Decorators) في بايثون! 🎭 إذا كنت تتساءل ما هي هذه الديكورات وكيف يمكنها أن تجعل كودك أكثر أناقة وكفاءة، فأنت في المكان الصحيح. الديكورات هي واحدة من الميزات القوية والفريدة في بايثون التي تسمح لك بـ"تزيين" أو تعديل سلوك الدوال والكلاسات دون الحاجة لتغيير الكود الأصلي لها.
🤔 ما هي الديكورات (Decorators)؟
ببساطة شديدة، الديكور هو مجرد دالة عادية في بايثون، ولكن لها مهمة خاصة: فهي تأخذ دالة أخرى كمدخل، وتقوم بإضافة وظائف إضافية عليها، ثم تعيد دالة جديدة معدلة.
فكر فيها كـ"غلاف" أو "إطار" نضعه حول دالة موجودة لتعزيز قدراتها. الميزة الرائعة أننا نفعل هذا دون المساس بالدالة الأصلية نفسها!
الفكرة الأساسية: دالة ← تدخل على ديكور ← تخرج دالة محسنة.
🔧 البنية الأساسية للديكور
لنبدأ بأبسط مثال ممكن لفهم الشكل العام للديكورات:
def my_decorator(func): # هذه هي الديكور - تأخذ دالة كمعامل
def wrapper(): # الدالة الداخلية التي "تغلف" الدالة الأصلية
# كود إضافي نريد تنفيذه قبل الدالة الأصلية
print("شيء ما يحدث قبل استدعاء الدالة!")
func() # استدعاء الدالة الأصلية
# كود إضافي نريد تنفيذه بعد الدالة الأصلية
print("شيء ما يحدث بعد استدعاء الدالة!")
return wrapper # إرجاع الدالة "المغلفة" الجديدة
في المثال أعلاه:
my_decoratorهي الديكور الرئيسيfuncهي الدالة التي نريد "تزيينها"wrapperهي الدالة الجديدة التي تحتوي على الوظائف الإضافية + الدالة الأصلية
🎯 تطبيق عملي: أول ديكور لك!
لنرى كيف نطبق هذا الديكور عملياً. تخيل أن لدينا دالة بسيطة ترحب بالمستخدم:
def say_hello():
print("مرحباً! أهلاً وسهلاً بك.")
الآن نريد "تزيين" هذه الدالة باستخدام الديكور الذي أنشأناه:
# تطبيق الديكور على الدالة
decorated_function = my_decorator(say_hello)
# استدعاء الدالة المزينة
decorated_function()
ماذا سيحدث عند التشغيل؟
شيء ما يحدث قبل استدعاء الدالة!
مرحباً! أهلاً وسهلاً بك.
شيء ما يحدث بعد استدعاء الدالة!
كما ترى، الدالة say_hello نفذت كما هي، ولكن أضفنا لها رسائل قبل وبعد تنفيذها!
🍬 السكر النحوي: @decorator
بايثون توفر طريقة أجمل وأكثر شيوعاً لاستخدام الديكورات باستخدام الرمز @:
@my_decorator
def say_hello():
print("مرحباً! أهلاً وسهلاً بك.")
# الآن يمكننا استدعاء الدالة مباشرة
say_hello()
هذه الطريقة تعادل تماماً الطريقة السابقة، ولكنها أكثر أناقة ووضوحاً. الرمز @my_decorator يخبر بايثون: "طبق ديكور my_decorator على الدالة التي تليني".
💡 مثال واقعي: ديكور قياس الوقت
لنخلق ديكوراً مفيداً يقيس وقت تنفيذ أي دالة:
import time
def timer_decorator(func):
def wrapper():
start_time = time.time() # تسجيل وقت البدء
func() # تنفيذ الدالة الأصلية
end_time = time.time() # تسجيل وقت الانتهاء
print(f"الوقت المستغرق: {end_time - start_time:.2f} ثانية")
return wrapper
# تطبيق الديكور
@timer_decorator
def slow_function():
print("جاري التنفيذ...")
time.sleep(2) # انتظار لمدة 2 ثانية لمحاكاة عملية بطيئة
print("اكتمل التنفيذ!")
# اختبار الديكور
slow_function()
النتيجة المتوقعة:
جاري التنفيذ...
اكتمل التنفيذ!
الوقت المستغرق: 2.00 ثانية
أليس هذا رائعاً؟ الآن يمكننا قياس وقت أي دالة بمجرد إضافة @timer_decorator فوقها!
🔄 ديكورات للدوال ذات المعاملات
ماذا لو كانت الدالة التي نريد تزيينها تأخذ معاملات؟ لا مشكلة! نجعل الديكور يتعامل مع أي عدد من المعاملات:
def smart_decorator(func):
def wrapper(*args, **kwargs): # تقبل أي عدد من المعاملات
print(f"جاري استدعاء الدالة {func.__name__}")
result = func(*args, **kwargs) # تمرير المعاملات للدالة الأصلية
print("تم الانتهاء من التنفيذ!")
return result # إرجاع نتيجة الدالة الأصلية
return wrapper
@smart_decorator
def greet(name, age):
return f"أهلاً {name}! عمرك {age} سنة."
@smart_decorator
def add_numbers(a, b):
return a + b
# اختبار الدوال
print(greet("أحمد", 25))
print(add_numbers(5, 3))
النتيجة:
جاري استدعاء الدالة greet
تم الانتهاء من التنفيذ!
أهلاً أحمد! عمرك 25 سنة.
جاري استدعاء الدالة add_numbers
تم الانتهاء من التنفيذ!
8
🚀 ديكورات متعددة ومتداخلة
يمكنك تطبيق أكثر من ديكور على نفس الدالة! بايثون تطبقهم من الأسفل إلى الأعلى:
def decorator1(func):
def wrapper():
print("ديكور 1 - قبل")
func()
print("ديكور 1 - بعد")
return wrapper
def decorator2(func):
def wrapper():
print("ديكور 2 - قبل")
func()
print("ديكور 2 - بعد")
return wrapper
@decorator1
@decorator2
def my_function():
print("الدالة الأصلية!")
my_function()
النتيجة:
ديكور 1 - قبل
ديكور 2 - قبل
الدالة الأصلية!
ديكور 2 - بعد
ديكور 1 - بعد
📝 ملخص الدرس
- الديكورات هي دوال تأخذ دوالاً أخرى وتعيد دوالاً معدلة
- نستخدم
@decorator_nameلتطبيق الديكور بطريقة أنيقة - الديكورات تسمح بإضافة وظائف للدوال دون تغيير كودها الأصلي
- يمكن للديكورات التعامل مع الدوال ذات المعاملات باستخدام
*argsو**kwargs - يمكن تطبيق أكثر من ديكور على نفس الدالة
🧠 تمارين تطبيقية
- أنشئ ديكوراً يطبع اسم الدالة قبل وبعد تنفيذها
- صمم ديكوراً يحول نتيجة أي دالة إلى أحرف كبيرة (uppercase)
- جرب تطبيق ديكورين مختلفين على نفس الدالة ولاحظ الترتيب
🎓 اختبر نفسك
التعليقات
شاركنا رأيك أو أسئلتك حول هذا المقال