از decorator ها بیشتر بدانیم

در برنامه نویسی decorator یک دیزاین پترن است که امکانات اضافی به یک object اضافه می کند. در پایتون دکوراتورها ابزاری هستند که امکانات اضافی را بدون تغییر تابع به توابع اضافه می کنند.دکوراتورها یکی از ابزارهای قدرتمند در python هستند که یک تابع را به عنوان argument می پذیرند و به کمک آنها می توان رفتار تابع argument را تغییر داد بدون اینکه تابع اصلی تغییر کند. به عبارت دیگر دکوراتورها این امکان را به برنامه نویس می دهند که رفتار توابع را به طور موقتی تغییر دهند. دکوراتورها با استفاده از decorator@ روی توابع اعمال می شوند.به طور کلی دکوراتور ها به صورت زیر تعریف می شوند:def mydecoratorfunction(some_function): # decorator function def inner_function(): # write code to extend the behavior of some_function() some_function() # call some_function # write code to extend the behavior of some_function() return inner_function # return a wrapper functionدکوراتورها روش ساده برای اجرای توابع higher-order هستند. توابع higher-order توابعی هستند که یک یا چند تابع را به عنوان آرگومان ورودی دریافت می کنند و یا یک تابع را return می کنند.در دکوراتور، function ها به عنوان ورودی به تابع دیگر پاس داده می شود و سپس داخل تابع wrapper صدا زده می شود. هدف اصلی از نوشتن دکوراتورها جلوگیری از نوشتن کدهای تکراری است به این صورت که توابعی را یکبار نوشته و از آنها برای متدهای مختلف استفاده می کنیم. مانند authorization که با استفاده از @ در بالای متد هایی که نیاز به اعتبار سنجی دارند قرار داده می شود.توابع در پایتون object هستند، بنابراین می توانند refrence داده شوند یا به عنوان متغیر به تابع دیگر ارسال شوند و یا توسط تابع دیگر return شوند. همچنین توابع می توانند درون یکدیگر اجرا شوند و متغیر های خود را به توابع درونی پاس دهند.مثال زیر را در نظر بگیرید که تابعی را در ورودی دریافت می کند و زمان اجرای آن را محاسبه می کند:import time import math def calculate_time(func): def inner(*args, **kwargs): begin = time.time() func(*args, **kwargs) end = time.time() print(&quotTotal time taken in : &quot, func.__name__, end - begin) return innerحال از تابع calculate_time با استفاده از @ می توان به صورت دکوراتور برای توابع دیگر استفاده کرد:@calculate_time def factorial(num): time.sleep(2) print(math.factorial(num))خروجی کد بالا به صورت زیر خواهد بود:>>>factorial(10) 3628800 Total time taken in : factorial 2.0061802864074707تشریح: در کد بالا تابع factorial(num) به عنوان ورودی به دکوراتور calculate_time ارسال می شود و در این دکوراتور اجرا شده و تابع inner(*args, **kwargs) زمان اجرای آن را محاسبه می کند.زنجیره دکوراتورها:می توان دکوراتورها را به صورت زنجیره ای از رکوراتورها به صورت زیر استفاده کرد:def decor1(func): def inner(): x = func() return x * x return inner def decor(func): def inner(): x = func() return 2 * x return inner @decor1 @decor def num(): return 10print(num())خروجی کد بالا عدد 400 خواهد بود.دکوراتور با functools:import functools def decorator(func): @functools.wraps(func) def wrapper_decorator(*args, **kwargs): value = func(*args, **kwargs) return value return wrapper_decoratorدکوراتورها با ورودی:def decorator(*args, **kwargs): print(&quotInside decorator&quot) def inner(func): print(&quotInside inner function&quot) print(&quotI like&quot, kwargs['like']) func() return inner@decorator(like = &quotgeeksforgeeks&quot) def func(): print(&quotInside actual function&quot)با اجرای کد بالا خروجی زیر را خواهیم داشت:Inside decorator Inside inner function I like geeksforgeeks Inside actual function