دليل ديكورات بايثون للمبرمجين المتقدمين

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

ما هي الديكورات؟

الديكورات هي وظائف تعدل سلوك وظيفة أخرى. فهي تغلف وظيفة أخرى لتوسيع سلوكها دون تعديل كودها صراحةً. يتم تعريف الديكورات باستخدام صيغة @decorator_name ويتم وضعها فوق تعريف الوظيفة.

بناء الجملة الأساسي للمُزيّن

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

def my_decorator(func):
    def wrapper():
        print("Something is happening before the function is called.")
        func()
        print("Something is happening after the function is called.")
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()

وظائف الديكور مع الوسائط

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

def repeat(num_times):
    def decorator_repeat(func):
        def wrapper(*args, **kwargs):
            for _ in range(num_times):
                func(*args, **kwargs)
        return wrapper
    return decorator_repeat

@repeat(num_times=3)
def greet(name):
    print(f"Hello, {name}!")

greet("Alice")

ديكورات التعشيش

يمكن دمج الديكورات لدمج سلوكيات متعددة. على سبيل المثال، يمكننا استخدام ديكورين أو أكثر في دالة واحدة.

def uppercase_decorator(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return result.upper()
    return wrapper

def repeat_decorator(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return result + result
    return wrapper

@repeat_decorator
@uppercase_decorator
def say_word(word):
    return word

print(say_word("hello"))

الديكورات القائمة على الفئات

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

class CountCalls:
    def __init__(self, func):
        self.func = func
        self.num_calls = 0

    def __call__(self, *args, **kwargs):
        self.num_calls += 1
        print(f"Call {self.num_calls} of {self.func.__name__!r}")
        return self.func(*args, **kwargs)

@CountCalls
def say_hello():
    print("Hello!")

say_hello()
say_hello()

استخدام functools.wraps للحفاظ على البيانات الوصفية

عند كتابة الديكورات، تفقد الدالة المزخرفة بياناتها الوصفية الأصلية، مثل اسمها وسلسلة الوثائق. يمكن استخدام الديكور functools.wraps لنسخ بيانات الدالة الوصفية الأصلية إلى الدالة المغلفة.

from functools import wraps

def my_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        print("Wrapper function executed before", func.__name__)
        return func(*args, **kwargs)
    return wrapper

@my_decorator
def display_info(name, age):
    """Displays name and age."""
    print(f"display_info ran with arguments ({name}, {age})")

print(display_info.__name__)  # Output: display_info
print(display_info.__doc__)   # Output: Displays name and age.

خاتمة

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