خبر و ترفند روز

خبر و ترفند های روز را اینجا بخوانید!

دکوراتورهای پایتون: آنها چه هستند و چگونه می توانید از آنها استفاده کنید؟

همه چیزهایی را که باید در مورد این ویژگی زبان هوشمند بدانید که به شما امکان می دهد توابع موجود را بدون تغییر آنها گسترش دهید، بیابید.

هنگام نوشتن کد، گاهی اوقات نیاز دارید که یک تابع را بدون تغییر مستقیم کد آن، گسترش دهید. در این شرایط، دکوراتورها می توانند کمک کنند.

دکوراتور نوع خاصی از عملکرد است که عملکرد دیگری را در بر می گیرد. آنها به شما امکان می دهند قبل و بعد از عملکرد اصلی کد اضافی اضافه کنید و روشی زیبا برای گسترش عملکردهای موجود ارائه می دهد.

دکوراتورها چگونه کار می کنند؟

جعبه های تزئین شده

توابع پایتون شهروندان درجه یک هستند، به این معنی که می توانید آنها را به متغیرها اختصاص دهید، آنها را به عنوان آرگومان به توابع دیگر ارسال کنید و آنها را از توابع برگردانید. این ویژگی ها ایجاد دکوراتورها را تسهیل می کند.

یک تابع دکوراتور عملکرد دیگری را برمی گرداند. این به عنوان یک متا تابع عمل می کند که عملکرد اضافی را به یک تابع هدف اضافه می کند. وقتی یک تابع را تزئین می کنید، پایتون تابع decorator را فراخوانی می کند و تابع هدف را به عنوان آرگومان ارسال می کند.

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

ایجاد یک تابع دکوراتور

برای ایجاد یک دکوراتور، تابعی را تعریف کنید که تابع هدف را به عنوان آرگومان می گیرد و تابع wrapper را برمی گرداند. تابع wrapper شامل عملکرد اضافی و فراخوانی تابع هدف است.

def decorator_func(target_func):
    def wrapper_func():
        # Action before calling target_func
        # ...

        # Call the target function
        target_func()
        
        # Action after calling target_func
        # ...

    return wrapper_func

در اینجا، decorator_func target_func را به عنوان یک آرگومان در نظر می گیرد. wrapper_func را برمی گرداند که target_func را فراخوانی می کند و شامل عملکرد اضافی است.

تزیین یک تابع با دکوراتور

برای اعمال دکوراتور به یک تابع هدف، از نحو @ استفاده کنید و دکوراتور را مستقیماً بالای تعریف تابع هدف قرار دهید.

@decorator_func
def my_function():
    # Function implementation
    pass

در اینجا decorator_func my_function را تزئین می کند. بنابراین، هر زمان که از my_function استفاده می کنید، پایتون decorator_func را فراخوانی می کند و my_function را به عنوان آرگومان ارسال می کند.

توجه داشته باشید که عملکرد دکوراتور از پرانتز باز و بسته کردن استفاده نمی کند.

مطلب مرتبط:   یک رمزگذار پیام با پایتون ایجاد کنید

برای وضوح، نحو @ بیشتر شبیه قند نحوی است. می‌توانید تابع هدف را به‌عنوان یک آرگومان مستقیماً به تابع دکوراتور منتقل کنید:

func = decorator_func(my_function)

رسیدگی به استدلال های عملکرد در دکوراتورها

برای رسیدگی به آرگومان های تابع در دکوراتورها، از *args و **kwargs در تابع wrapper استفاده کنید. اینها به طراح اجازه می دهد تا هر تعداد آرگومان موقعیتی و کلیدی را بپذیرد.

def decorator_func(target_func):
    def wrapper_func(*args, **kwargs):
        # before calling target_func with args and kwargs
        # ...

        # Call the target function with arguments
        result = target_func(*args, **kwargs)

        # after calling target_func
        # ...
        return result

    return wrapper_func

*args و **kwargs در wrapper_func تضمین می‌کنند که دکوراتور می‌تواند هر آرگومان را که به تابع هدف ارسال می‌کنید، مدیریت کند.

دکوراتورها با استدلال

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

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

@my_decorator(2)
def greet(name):
    print(f"Hello, {name}.")

تابع my_decorator عدد (2) را به عنوان آرگومان می گیرد و تابع wrapper را برمی گرداند. آن تابع یک تابع درونی را برمی گرداند که تابع تزئین شده (در این مورد سلام) را تعداد معینی بار (2) فراخوانی می کند. به طوری که:

greet("Prince")

“سلام، شاهزاده” را دو بار چاپ خواهد کرد.

کاربردهای عملی دکوراتورها

می‌توانید از دکوراتورها برای اهداف مختلفی مانند ثبت گزارش، ذخیره‌سازی، اعتبارسنجی ورودی و بهینه‌سازی عملکرد استفاده کنید.

دکوراتور چوب

برای ثبت اطلاعات مربوط به اجرای یک تابع می توانید از دکوراتور لاگ استفاده کنید. این می تواند به اشکال زدایی یا نظارت بر رفتار توابع خاص کمک کند.

import logging

def my_logger(func):
    def wrapper(*args, **kwargs):
        logging.info("Entering function: %s", func.__name__)
        result = func(*args, **kwargs)
        logging.info("Exiting function: %s", func.__name__)
        return result

    return wrapper

دکوراتور زمان بندی

برای اندازه گیری زمان اجرای اجرای یک تابع می توانید از دکوراتور زمان بندی استفاده کنید. برای پروفایل یا بهینه سازی کد مفید است.

import time

def timing_decorator(target_func):
    def wrapper_func(*args, **kwargs):
        start_time = time.time()
        result = target_func(*args, **kwargs)
        end_time = time.time()
        total = end_time - start_time
        print(f"Function {target_func.__name__} took {total} seconds to run")
        return result

    return wrapper_func

از دکوراتورها استفاده کنید:

@my_logger
@timing_decorator
def bg_task(n):
    print(f"Background Task, {n}.")
    return "Result !!!"

if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO)
    print(bg_task("CPU is Dancing"))

اکنون هنگام اجرای تابع، اشکال زدایی و خلاصه مدت زمان آن را مشاهده خواهید کرد.

مطلب مرتبط:   مقدمه ای بر React Context API

خروجی دکوراتور ورود به سیستم و زمان بندی

دکوراتور مجوز

برای بررسی اینکه آیا کاربر مجوزهای لازم برای دسترسی به یک عملکرد خاص را دارد، می توانید از یک تزئین کننده مجوز استفاده کنید. اکثر چارچوب های وب از این ویژگی برای افزودن یک لایه امنیتی استفاده می کنند. یک مثال رایج دکوراتور @login_required جنگو است.

def authorization_decorator(target_func):
    def wrapper_func(*args, **kwargs):
        if is_user_authorized():
            result = target_func(*args, **kwargs)
            return result
        else:
            raise PermissionError("Unauthorized access")

    return wrapper_func

این مثال‌ها برخی از موارد استفاده رایج برای دکوراتورها را نشان می‌دهد. بسته به نیازهای خاص خود می توانید دکوراتورهایی برای اهداف مختلف ایجاد کنید.

مفاهیم دکوراتور پیشرفته

اجرا و استفاده از دکوراتورها آسان است. اما آنها همچنین قدرتمند هستند و می توانند انعطاف پذیری و کنترل بیشتری را ارائه دهند.

دکوراتورهای کلاسی

پایتون علاوه بر دکوراتورهای مبتنی بر عملکرد، از دکوراتورهای کلاس محور نیز پشتیبانی می کند.

دکوراتور مبتنی بر کلاس کلاسی است که روش جادویی __call__ را تعریف می کند و به شما امکان می دهد از کلاس به عنوان دکوراتور استفاده کنید.

class DecoratorClass:
    def __init__(self, target_func):
        self.target_func = target_func

    def __call__(self, *args, **kwargs):
        # Decorator implementation
        print("Calling function")
        result = self.target_func(*args, **kwargs)
        print("Function called")
        return result

این مثال یک کلاس دکوراتور را تعریف می کند. وقتی تابعی را با DecoratorClass تزئین می‌کنید، پایتون متد جادویی __call__ را فراخوانی می‌کند که عملکرد دکوراتور را برای تابع هدف اعمال می‌کند.

دکوراتورهای مبتنی بر کلاس می توانند با ذخیره اطلاعات در متغیرهای نمونه، وضعیت را در چندین تماس حفظ کنند. این به شما امکان می دهد تا اجرای دکوراتورهای پیشرفته و انعطاف پذیرتری داشته باشید.

دکوراتورهای تودرتو و زنجیر

فرض کنید باید انواع مختلف عملکرد را در یک واحد واحد برای اقدامات مرتبط روی یک تابع ترکیب کنید. شما می توانید با استفاده از چندین دکوراتور برای یک عملکرد واحد به این امر دست یابید.

def decorator1(func):
    def wrapper(*args, **kwargs):
        print("Decorator1...")
        return func(*args, **kwargs)

    return wrapper

def decorator2(func):
    def wrapper(*args, **kwargs):
        print("Decorator2...")
        return func(*args, **kwargs)

    return wrapper

@decorator1
@decorator2
def my_function(n):
    print(n)

اینجا هم decorator1 و هم decorator2 my_function را تزئین می کنند. هر زمان که از my_function استفاده می کنید، ابتدا عملکرد decorator1 و سپس decorator2 اعمال می شود.

مطلب مرتبط:   12 تک لاینر مفید پایتون که باید بدانید

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

مزایای تزئینات

دکوراتورها چندین مزیت را ارائه می دهند که آنها را در بسیاری از پروژه های پایتون ضروری می کند:

  • قابلیت استفاده مجدد کد: قابلیت استفاده مجدد کد را با جدا کردن نگرانی های مقطعی از منطق اصلی ارتقا می دهد.
  • اصل DRY: با اعمال یک عملکرد مشابه برای چندین عملکرد بدون تکرار کد، به اصل خودت تکرار نکن پایبند است.
  • خوانایی و قابلیت نگهداری: خوانایی و قابلیت نگهداری کد را با متمرکز و واضح نگه داشتن عملکرد اصلی افزایش می دهد.
  • سبک پایتونیک: با تأکید بر کدهای تمیز، رسا و خوانا، با سبک پایتونیک هماهنگ می شود.

به این دلایل، در صورت امکان باید از دکوراتورها استفاده کنید.

بهترین روش ها برای استفاده از دکوراتورها

هنگام کار با دکوراتورها باید از بهترین شیوه های خاص پیروی کنید:

  • عملکرد دکوراتور را بر روی یک نگرانی خاص، مانند ورود به سیستم یا ذخیره کردن، متمرکز نگه دارید. این کد مدولار را ترویج می کند و تزئینات را همه کاره تر می کند.
  • با استفاده از پارامترها و اجتناب از مقادیر کدگذاری شده، دکوراتورها را قابل تنظیم کنید. این به شما امکان می دهد تا رفتار دکوراتور را هنگام اعمال آن در عملکردهای مختلف سفارشی کنید.
  • توضیحی واضح و مختصر از هدف دکوراتور، پارامترهای آن (در صورت وجود)، و رفتار مورد انتظار هنگام اعمال بر یک تابع ارائه دهید.
  • اگر دکوراتور دارای عوارض جانبی است، مانند تغییر رفتار عملکرد یا ایجاد وابستگی های اضافی، به وضوح این اثرات را برای مراجعات بعدی مستند کنید.
  • تست های واحد را برای دکوراتورهای خود بنویسید تا مطمئن شوید که همانطور که انتظار دارید رفتار می کنند. سناریوهای مختلف و موارد لبه را برای پوشش طیف گسترده ای از موقعیت ها آزمایش کنید.

کار با توابع در پایتون

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

درک نحوه تعریف و استفاده از توابع برای برنامه نویسی موثر پایتون ضروری است.