مستوى المقال: متوسط — يفترض إنك تعرف Python أساسي و تعرف تكتب function وتستدعيها.
Decorators في Python: السر اللي بيخلّي Flask و FastAPI بهذه البساطة
لو بتكتب نفس الخمس سطور لتسجيل الـ logs قبل وبعد كل function، أنت بتنسخ 200 سطر زيادة في ملف فيه 40 function. Decorator واحد بـ 8 سطور بيشتغل على الـ 40 function معًا، بدون ما تلمس ولا واحدة فيهم.
المشكلة باختصار
كل function في تطبيقك محتاج تلات حاجات إضافية: logging، قياس زمن، error handling. لو كتبتهم جوّا الـ function، الـ business logic بيختفي وسط الـ noise. لو نسيتهم في function واحدة، بتفقد القياسات في النقطة دي بالظبط. الـ Decorator بيحل المشكلتين معًا، وبيخلّي الكود الأصلي نضيف تماماً.
تخيل أمين الفندق اللي بيسجّل كل ضيف
تخيّل فندق فيه 40 موظف بيستقبلوا الزبائن. كل واحد منهم محتاج يسجّل ثلاث معلومات لكل ضيف: مين دخل، الساعة كام، طلب إيه. لو خلّيت كل موظف يكتب ده بنفسه، نص الموظفين هينسوا، والباقي هيسجّلوا بصيغ مختلفة بتكسر التقارير.
الحل العملي: تحط أمين واحد عند الباب يسجّل كل اللي بيدخل ويبعتهم للموظف المختص. الموظفين يركزوا على شغلهم الأصلي. الـ Decorator في Python بيلعب نفس دور الأمين ده بالظبط — طبقة بتلف الـ function وبتضيف سلوك إضافي بدون ما الـ function نفسها تعرف عنها أي حاجة.
تعريف علمي: ايه الـ Decorator في Python بالظبط
حسب PEP 318 الرسمي اللي اتقبل في Python 2.4، الـ Decorator هو callable بياخد callable تاني كـ argument وبيرجّع callable جديد بدلًا منه. الفكرة الأصلية بتعتمد على إن الـ functions في Python First-Class Objects — يعني تقدر تمرّرها زي ما بتمرّر integer أو string.
الترميز اللي بتشوفه فوق الـ function:
@measure_time
def process_order(order_id):
...
هو مجرد syntactic sugar للسطر التالي:
def process_order(order_id):
...
process_order = measure_time(process_order)
يعني فيه استبدال للـ process_order الأصلية بنسخة ملفوفة. مفيش سحر، مجرد إعادة تعيين.