ما هي ديكوريتورز في Python
إذا كنت قد كتبت كودًا بلغة Python لأكثر من أسبوع، فبالتأكيد رأيت الرمز @ فوق دالة. هذا هو الـ decorator — أداة برمجية قوية وسهلة الفهم.
الديكوريتورز في Python تسمح لك بـ "تغليف" دالة داخل دالة أخرى. فهي تغير أو توسع سلوك الدالة دون تعديل الكود الأصلي. تُستخدم الديكوريتورز في كل مكان: في Flask، Django، FastAPI، pytest، وحتى في المكتبة القياسية للغة Python.
كيف تعمل الديكوريتورز
أساسيات الديكوريتورز
الديكوريتور هو دالة تستقبل دالة أخرى وتعيد دالة جديدة أو معدلة.
def decorator(func):
def wrapper():
print("قبل الاستدعاء")
func()
print("بعد الاستدعاء")
return wrapper
@decorator
def say_hello():
print("مرحبًا!")
say_hello()
نتيجة التنفيذ:
قبل الاستدعاء
مرحبًا!
بعد الاستدعاء
الرمز @decorator هو مجرد اختصار نحوي للكتابة التالية:
say_hello = decorator(say_hello)
البنية الداخلية للديكوريتورز
لفهم الديكوريتورز في Python، يجب أن تعرف المفاهيم الأساسية التالية:
- في Python، الدوال هي كائنات من الدرجة الأولى
- يمكن تمرير الدوال كوسائط لدوال أخرى
- يمكن تعريف دوال داخل دوال أخرى
- توجد آلية الإغلاق (closure)
النمط العام للديكوريتور
النمط الأدنى للديكوريتور يكون كالتالي:
def decorator(func):
def wrapper(*args, **kwargs):
# إجراءات قبل تنفيذ الدالة
result = func(*args, **kwargs)
# إجراءات بعد تنفيذ الدالة
return result
return wrapper
أمثلة عملية على الديكوريتورز
ديكوريتور قياس وقت التنفيذ
import time
def timing(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
execution_time = time.time() - start
print(f"استغرقت {func.__name__} {execution_time:.4f} ثانية")
return result
return wrapper
@timing
def slow_func():
time.sleep(1)
return "تمت العملية"
slow_func()
هذا الديكوريتور مفيد لقياس أداء الدوال وتحسين الكود.
ديكوريتور التحقق من الصلاحية
def require_admin(func):
def wrapper(user, *args, **kwargs):
if user != "admin":
raise PermissionError("الوصول ممنوع")
return func(user, *args, **kwargs)
return wrapper
@require_admin
def delete_database(user):
print("تم حذف قاعدة البيانات!")
return True
delete_database("admin") # تنفيذ ناجح
هذا الديكوريتور يعزز أمان التطبيق من خلال التحكم في الوصول إلى الدوال الحساسة.
ديكوريتور تسجيل العمليات
import logging
from functools import wraps
def log_calls(func):
@wraps(func)
def wrapper(*args, **kwargs):
logging.info(f"استدعاء الدالة {func.__name__} بالوسائط {args}, {kwargs}")
try:
result = func(*args, **kwargs)
logging.info(f"تم تنفيذ الدالة {func.__name__} بنجاح")
return result
except Exception as e:
logging.error(f"خطأ في الدالة {func.__name__}: {e}")
raise
return wrapper
ديكوريتورز مع وسائط
إنشاء مصنع للديكوريتورز
عندما يحتاج الديكوريتور إلى استقبال معاملات، يتم إنشاء مصنع للديكوريتورز:
def repeat(n):
def decorator(func):
def wrapper(*args, **kwargs):
results = []