المزخرفات في بايثون

المزخرفات في بايثون

تشرح هذه المقالة المزخرفات في بايثون۔

YouTube Video

المزخرفات في بايثون

المزخرفات في بايثون هي ميزة قوية تُستخدم لإضافة وظائف إضافية إلى الدوال أو الأساليب.۔ تتيح لك المزخرفات إضافة وظائف جديدة دون تعديل الكود الحالي، مما يعزز إمكانية إعادة استخدام الكود وصيانته.۔

أساسيات المزخرفات

تعمل المزخرفات في بايثون عن طريق أخذ دالة كمعطى وإرجاع دالة جديدة بوظائف إضافية.۔ باستخدام المزخرفات، يمكنك بسهولة إضافة معالجة مسبقة أو لاحقة إلى الدوال.۔

بدون المزخرفات، يتطلب تغيير سلوك الدالة تحرير الدالة نفسها مباشرة. مع المزخرفات، يمكنك توسيع الوظائف دون تعديل التنفيذ الأصلي.۔

البنية الأساسية للمزخرف

 1def my_decorator(func):
 2    def wrapper():
 3        print("Before the function call")
 4        func()
 5        print("After the function call")
 6    return wrapper
 7
 8@my_decorator
 9def say_hello():
10    print("Hello!")
11
12say_hello()

في هذا المثال، تعمل دالة my_decorator كزخرفة، حيث تغلف دالة say_hello.۔ يتم تطبيق المزخرف باستخدام صيغة @my_decorator، وعند استدعاء say_hello()، يتم تنفيذ المعالجة المسبقة واللاحقة التي يقدمها المزخرف تلقائيًا.۔

كيف تعمل المزخرفات

يعمل المزخرفون بالخطوات التالية۔

  1. يأخذ المزخرف دالة (أو أسلوبًا) كمعطى.۔

  2. يعرف دالة تغليف لتشغيل الدالة الأصلية.۔

  3. تنفذ دالة التغليف معالجة إضافية قبل أو بعد تشغيل الدالة الأصلية.۔

  4. يرجع المزخرف دالة التغليف.۔ نتيجة لذلك، يتم استبدال الدالة الأصلية بدالة جديدة مزخرفة.۔

المزخرفات للدوال ذات المعطيات

عند تطبيق مزخرف على دالة تحتوي على معطيات، يجب تعديل دالة التغليف لقبول تلك المعطيات.۔

 1def my_decorator(func):
 2    def wrapper(*args, **kwargs):
 3        print("Before the function call")
 4        result = func(*args, **kwargs)
 5        print("After the function call")
 6        return result
 7    return wrapper
 8
 9@my_decorator
10def greet(name):
11    print(f"Hello, {name}!")
12
13greet("Alice")

عن طريق استخدام *args و **kwargs، يمكن التعامل مع الدوال التي تقبل أي عدد من المعطيات والمعطيات المفتاحية.۔ يتيح ذلك تطبيق المزخرفات بشكل عام على الدوال ذات أي نوع من المعطيات.۔

أمثلة على تطبيق المزينات

مزين لتسجيل العمليات

تُستخدم المزينات غالبًا لإضافة وظيفة تسجيل العمليات۔ على سبيل المثال، من خلال إنشاء مزين يُسجل قبل وبعد تنفيذ وظيفة، يمكنك تسجيل متى يتم استدعاء الوظيفة ومدة تنفيذها۔

 1import time
 2
 3def log_time(func):
 4    def wrapper(*args, **kwargs):
 5        start_time = time.time()
 6        print(f"Calling function '{func.__name__}'...")
 7        result = func(*args, **kwargs)
 8        end_time = time.time()
 9        print(f"Function '{func.__name__}' completed in {end_time - start_time} seconds")
10        return result
11    return wrapper
12
13@log_time
14def long_task(duration):
15    time.sleep(duration)
16    print("Task completed!")
17
18long_task(2)

في هذا المثال، يقوم المزين log_time بقياس وقت تنفيذ الوظيفة وإخراج النتيجة كتسجيل۔ يتم تغليف وظيفة long_task بالمزين ويتم تسجيل وقت تنفيذها أثناء التشغيل۔

مزين لإدارة الصلاحيات

يمكن أيضًا استخدام المزينات لإدارة الصلاحيات۔ على سبيل المثال، يمكنك تقييد العمليات من خلال التحقق مما إذا كان لدى المستخدم الصلاحيات المحددة۔

 1def requires_permission(user_role):
 2    def decorator(func):
 3        def wrapper(*args, **kwargs):
 4            if user_role != "admin":
 5                print("Permission denied!")
 6                return
 7            return func(*args, **kwargs)
 8        return wrapper
 9    return decorator
10
11@requires_permission("admin")
12def delete_user(user_id):
13    print(f"User {user_id} has been deleted.")
14
15delete_user(123)  # Executed
16delete_user = requires_permission("guest")(delete_user)
17delete_user(456)  # Permission denied!

المزين requires_permission يقيّد تنفيذ وظيفة بناءً على دور المستخدم۔ من خلال تجميع مثل هذا المنطق في مزين، يمكنك منع عملية إدارة الصلاحيات من التشتت في جميع أنحاء الشيفرة، مما يحسن القابلية للقراءة۔

تداخل المزينات

من الممكن تطبيق مزينات متعددة۔ عند تطبيق مزينات متعددة على وظيفة واحدة، يتم تنفيذها بالترتيب من الأعلى إلى الأسفل۔

 1def uppercase(func):
 2    def wrapper(*args, **kwargs):
 3        result = func(*args, **kwargs)
 4        return result.upper()
 5    return wrapper
 6
 7def exclaim(func):
 8    def wrapper(*args, **kwargs):
 9        result = func(*args, **kwargs)
10        return result + "!"
11    return wrapper
12
13@uppercase
14@exclaim
15def greet(name):
16    return f"Hello, {name}"
17
18print(greet("Alice"))  # "HELLO, ALICE!"

في هذا المثال، يتم تطبيق مزينين على وظيفة greet۔ المزين @exclaim يضيف علامة تعجب إلى نهاية النص، بينما يقوم @uppercase بتحويل النص إلى أحرف كبيرة۔

مزينات لطرق الصفوف

يمكن أيضًا استخدام المزينات مع طرق الصفوف۔ يُعتبر هذا مفيدًا بشكل خاص عندما تريد التحكم في سلوك الطرق داخل الصف۔ عند تطبيق المزينات على طرق الصفوف، يجب أن تكون منتبهًا للحجج مثل self أو cls۔

 1def log_method_call(func):
 2    def wrapper(self, *args, **kwargs):
 3        print(f"Calling method '{func.__name__}'...")
 4        return func(self, *args, **kwargs)
 5    return wrapper
 6
 7class MyClass:
 8    @log_method_call
 9    def greet(self, name):
10        print(f"Hello, {name}")
11
12obj = MyClass()
13obj.greet("Bob")

في هذا المثال، يتم تطبيق المزين log_method_call على الطريقة greet لإنتاج تسجيل عند استدعاء الطريقة۔

التحذيرات المتعلقة بالمزينات

هناك بعض الاعتبارات عند استخدام المزينات۔ يمكن أن تغير المزينات اسم الوظيفة الأصلية أو سلسلة التوثيق الخاصة بها (مثل __name__ أو __doc__)، لذلك يُوصى باستخدام functools.wraps للحفاظ على هذه المعلومات۔

1import functools
2
3def my_decorator(func):
4    @functools.wraps(func)
5    def wrapper(*args, **kwargs):
6        print("Before the function call")
7        return func(*args, **kwargs)
8    return wrapper

يضمن استخدام @functools.wraps تمرير بيانات الوظيفة الأصلية بشكل صحيح إلى الوظيفة المغلفة۔

الملخص

مُزَيِّنات بايثون هي أداة قوية جدًا تتيح لك إضافة وظائف إضافية إلى الدوال والأساليب بطريقة مختصرة.۔ يمكن استخدامها في مواقف مختلفة لتقليل تكرار الشيفرة وتحسين سهولة الصيانة وإعادة الاستخدام.۔ من خلال فهم كيفية عمل المُزَيِّنات، يمكنك كتابة شيفرة أكثر كفاءة ومرونة.۔

يمكنك متابعة المقالة أعلاه باستخدام Visual Studio Code على قناتنا على YouTube.۔ يرجى التحقق من القناة على YouTube أيضًا.۔

YouTube Video