python, آموزش قدم به قدم پایتون, پایتون

Decorator در پایتون

Decorator در پایتون


توابع دکوراتور (Decorator) یکی از قابلیت‌های مهم در زبان برنامه‌نویسی پایتون هستند. این ابزار قدرتمند به برنامه‌نویسان امکان می‌دهد تا توابع خود را به سادگی تغییر دهند و عملکرد آن‌ها را بهبود بخشند. توابع Decorator برای کارهایی مانند نظارت بر ورودی‌ها، لاگ‌گذاری، اندازه‌گیری زمان اجرا و بسیاری از کارهای دیگر مفید هستند. در این مقاله، ما با مفهوم توابع Decorator در پایتون آشنا خواهیم شد و نحوه استفاده از آن‌ها را بررسی می‌کنیم.

مفهوم توابع Decorator

توابع دکوراتور (Decorators) در پایتون به عنوان یک نوع توابع معمولی تعریف می‌شوند. اما تفاوت اصلی آن‌ها در این است که توابع دکوراتور قادر به تغییر رفتار توابع دیگر هستند. به عبارت دقیق‌تر، یک تابع دکوراتور توانایی اضافه کردن یک عملکرد اضافی به یک تابع دیگر را دارد، بدون اینکه کد تابع اصلی را تغییر دهد.

چرا از توابع دکوراتور استفاده می‌شود؟

استفاده از توابع دکوراتور دارای مزایا مختلفی است. در زیر چند دلیل برای استفاده از توابع دکوراتور در پایتون آورده‌ایم:

  1. جداسازی عملکرد: با استفاده از توابع دکوراتور، می‌توانید عملکردهای مختلفی را به توابع اضافه کنید، به جای اینکه همه کد درون یک تابع بزرگ جا داده شود. این باعث افزایش خوانایی کد و تقسیم منطق برنامه به اجزای کوچکتر می‌شود.
  2. نظارت بر ورودی‌ها: با توابع دکوراتور می‌توانید ورودی‌های یک تابع را بررسی کنید و اطمینان حاصل کنید که آن‌ها از قوانین مشخصی پیروی می‌کنند. به عنوان مثال، یک توابع دکوراتور می‌تواند اعتبارسنجی ورودی‌ها را انجام دهد و از ورودی‌های نادرست جلوگیری کند.
  3. لاگ‌گذاری (Logging): توابع دکوراتور معمولاً برای ثبت اطلاعات مربوط به اجرای توابع استفاده می‌شوند. این امر برای ارائه اطلاعات بهتر به منظور دیباگ و نظارت بر عملکرد برنامه مفید است.
  4. زمان‌بندی اجرا: با توابع دکوراتور می‌توانید زمان اجرای یک تابع را اندازه‌گیری و اطلاعات مربوط به زمان اجرا را ثبت کنید. این اطلاعات می‌تواند برای بهبود عملکرد و بهینه‌سازی برنامه مفید باشد.

نحوه استفاده از توابع Decorator در پایتون

توابع Decorator در پایتون به عنوان یک توابع معمولی تعریف می‌شوند. برای استفاده از یک تابع دکوراتور ، شما باید آن را به عنوان یک دکوراتور به یک تابع دیگر اعمال کنید. برای این کار، شما از @ استفاده می‌کنید. دلیل استفاده از @ این است که کد توابع دکوراتور به تابع اصلی اضافه می‌شود.

مثال: تعریف یک تابع دکوراتور

def my_decorator(func):
    def wrapper():
        print("قبل از اجرای تابع")
        func()
        print("بعد از اجرای تابع")
    return wrapper

@my_decorator
def say_hello():
    print("سلام!")

say_hello()

در این مثال، ما یک تابع دکوراتور به نام my_decorator تعریف کرده‌ایم که یک تابع دیگر (func) را صدا می‌زند. درون این تابع دکوراتور یک تابع دیگر به نام wrapper تعریف کرده که قبل و بعد از اجرای تابع func پیام‌هایی را چاپ می‌کند.

سپس با استفاده از @my_decorator، ما تابع say_hello را دکوراتور کرده‌ایم. حالا اگر تابع say_hello را فراخوانی کنیم، عملکرد آن توسط تابع دکوراتور my_decorator تغییر می‌کند.

خروجی:

قبل از اجرای تابع
سلام!
بعد از اجرای تابع

توابع Decorator در پایتون با پارامتر

توابع دکوراتور می‌توانند پارامترها را نیز بپذیرند و به توابع دیگر اعمال شوند. برای این کار، شما باید تعداد متغیرهای پارامتر تابع دکوراتور را مشخص کنید.

مثال: توابع دکوراتور با پارامتر

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

@repeat(3)
def say_hello(name):
    print(f"سلام، {name}!")

say_hello("آرمان")

مثال بالا، ما یک تابع دکوراتور به نام repeat تعریف کرده‌ایم که تعداد تکرار اجرای تابع دیگر (func) را به عنوان پارامتر دریافت می‌کند. سپس درون خود تابع دکوراتور my_decorator تعریف می‌کند که پارامترها را به تابع wrapper منتقل می‌کند. تابع wrapper مشابه مثال قبلی عمل کرده اما عملکرد تعداد تکرار تابع func را مقدار مشخص شده در repeat تعیین می‌کند.

سپس با استفاده از @repeat(3)، ما تابع say_hello را دکوراتور کرده‌ایم و مقدار 3 به عنوان تعداد تکرار اجرای تابع مشخص کرده‌ایم. حالا اگر تابع say_hello را با یک پارامتر فراخوانی کنیم، عملکرد آن توسط تابع دکوراتور repeat تغییر خواهد کرد.

خروجی:

سلام، آرمان!
سلام، آرمان!
سلام، آرمان!

توابع دکوراتور چند لایه

می‌توانید چندین تابع دکوراتور را به یک تابع اعمال کنید. در این صورت، توابع دکوراتور به ترتیب اعمال می‌شوند. این ترتیب را در مثال بعدی خواهید دید.

مثال: توابع دکوراتور چند لایه

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 say_hello():
    print("سلام!")

say_hello()

در این مثال، ما دو تابع دکوراتور به نام decorator1 و decorator2 تعریف کرده‌ایم. هر کدام از این توابع دکوراتور یک تابع دیگر را به عنوان ورودی دریافت می‌کنند و تغییراتی بر روی عملکرد آن اعمال می‌کنند.

سپس با استفاده از @decorator1 و @decorator2، ما تابع say_hello را دکوراتور کرده‌ایم. حالا اگر تابع say_hello را فراخوانی کنیم، توابع دکوراتور به ترتیب اعمال می‌شوند و عملکرد تابع say_hello تغییر می‌کند.

خروجی:

تابع دکوراتور 1: قبل از اجرای تابع
تابع دکوراتور 2: قبل از اجرای تابع
سلام!
تابع دکوراتور 2: بعد از اجرای تابع
تابع دکوراتور 1: بعد از اجرای تابع

توابع دکوراتور سفارشی

می‌توانید توابع دکوراتور سفارشی خود را تعریف کنید و از آن‌ها برای تغییر عملکرد توابع استفاده کنید. این توابع دکوراتور سفارشی می‌توانند به توانایی‌های شما در ایجاد کدهای بزرگتر و پیچیده‌تر کمک کنند.

مثال: توابع دکوراتور سفارشی

def custom_decorator(prefix):
    def decorator(func):
        def wrapper(*args, **kwargs):
            print(f"{prefix}: قبل از اجرای تابع")
            func(*args, **kwargs)
            print(f"{prefix}: بعد از اجرای تابع")
        return wrapper
    return decorator

@custom_decorator("دکوراتور 1")
def say_hello():
    print("سلام!")

@custom_decorator("دکوراتور 2")
def say_goodbye():
    print("خداحافظ!")

say_hello()
say_goodbye()

در این مثال، ما یک تابع دکوراتور سفارشی به نام custom_decorator تعریف کرده‌ایم که یک پیشوند (مثل “تزئینی 1” یا “تزئینی 2”) را به عنوان ورودی می‌پذیرد. سپس این تابع دکوراتور سفارشی یک تابع دکوراتور ایجاد می‌کند که عملکردی مشابه مثال‌های قبلی دارد.

سپس با استفاده از @custom_decorator("تزئینی 1") و @custom_decorator("تزئینی 2")، ما توابع say_hello و say_goodbye را دکوراتور کرده‌ایم. حالا اگر این دو تابع را فراخوانی کنیم، توابع دکوراتور با پیشوندهای مختلف به ترتیب اعمال می‌شوند و عملکرد هر تابع تغییر می‌کند.

خروجی:

دکوراتور 1: قبل از اجرای تابع
سلام!
دکوراتور 1: بعد از اجرای تابع
دکوراتور 2: قبل از اجرای تابع
خداحافظ!
دکوراتور 2: بعد از اجرای تابع

توابع دکوراتور قبل و بعد

با استفاده از توابع دکوراتور می‌توانید عملکرد یک تابع را قبل یا بعد از اجرا تغییر دهید. به این ترتیب، می‌توانید کدهای پیچیده‌تری ایجاد کنید که به توابع اصلی خود عملکرد اضافی اعمال می‌کنند.

مثال: توابع دکوراتور قبل و بعد

def before_and_after(func):
    def wrapper(*args, **kwargs):
        print("قبل از اجرای تابع")
        result = func(*args, **kwargs)
        print("بعد از اجرای تابع")
        return result
    return wrapper

@before_and_after
def say_hello():
    print("سلام!")

result = say_hello()
print(f"نتیجه: {result}")

در این مثال، ما یک تابع دکوراتور به نام before_and_after تعریف کرده‌ایم که عملکرد یک تابع را تغییر می‌دهد. این تابع دکوراتور یک تابع دیگر را به عنوان ورودی دریافت می‌کند و در داخل آن، قبل از اجرای تابع اصلی یک پیام چاپ می‌کند و بعد از اجرای تابع اصلی نیز یک پیام دیگر چاپ می‌کند.

سپس با استفاده از @before_and_after، ما تابع say_hello را دکوراتور کرده‌ایم. حالا اگر تابع say_hello را فراخوانی کنیم، عملکرد آن توسط تابع دکوراتور before_and_after تغییر خواهد کرد.

خروجی:

قبل از اجرای تابع
سلام!
بعد از اجرای تابع
نتیجه: None

استفاده از توابع دکوراتور در واقعیت

توابع دکوراتور یکی از ابزارهای قدرتمند در پایتون هستند که به برنامه‌نویسان امکان می‌دهند تا عملکرد توابع را تغییر دهند و کدهای تکراری را کاهش دهند. با استفاده از توابع دکوراتور ، می‌توانید منطق برنامه خود را به طور شفاف‌تر ارتقا دهید و کد بهتری ایجاد کنید.

از آنجا که توابع دکوراتور می‌توانند به تعداد بی‌پایانی توالی شوند، باید مراقب باشید تا باعث پیچیدگی زیاد در کدهای خود نشوید. همچنین، توجه داشته باشید که توابع دکوراتور اغلب منطق برنامه را به شکل مخفی تغییر می‌دهند، بنابراین باید با دقت آن‌ها را طراحی و استفاده کنید.

در پایان، توابع دکوراتور ابزار قدرتمندی هستند که به شما امکان می‌دهند کدتان را تمیزتر و قابل‌مدیریت‌تر کنید. شما می‌توانید از آن‌ها برای ایجاد کدهای پیچیده‌تر و توسعه‌پذیرتری در پروژه‌های خود بهره‌برداری کنید

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *