دکوراتورها (Decorators)
دکوراتور (Decorator
) در پایتون ابزاری است که امکان افزودن رفتار اضافه به یک تابع را بدون تغییر در کد اصلی آن فراهم می کند. دکوراتور یک تابع است که تابع دیگر را به عنوان ورودی می گیرد و خروجی آن یک تابع جدید است.
نمونه ساده دکوراتور
ابتدا دکوراتور تعریف می شود، سپس با قرار دادن @decorator_name
بالای تابع، اعمال می گردد:
def changecase(func):
def myinner():
return func().upper()
return myinner
@changecase
def myfunction():
return "Hello Sally"
print(myfunction())
در این مثال، تابع myfunction
با دکوراتور changecase
تغییر رفتار داده است.
کاربرد روی چند تابع
می توانید یک دکوراتور را روی چند تابع مختلف اعمال کنید:
@changecase
def myfunction():
return "Hello Sally"
@changecase
def otherfunction():
return "I am speed!"
print(myfunction())
print(otherfunction())
تابع تزئین شده با آرگومان
اگر تابع شما نیاز به آرگومان دارد، کافی است آن ها را به تابع داخلی پاس دهید:
def changecase(func):
def myinner(x):
return func(x).upper()
return myinner
@changecase
def myfunction(name):
return "Hello " + name
print(myfunction("John"))
استفاده از *args و **kwargs
برای پشتیبانی از تعداد نامشخص آرگومان ها، از *args
و **kwargs
استفاده کنید:
def changecase(func):
def myinner(*args, **kwargs):
return func(*args, **kwargs).upper()
return myinner
@changecase
def myfunction(name):
return "Hello " + name
print(myfunction("John"))
دکوراتور با آرگومان
دکوراتورها می توانند خودشان نیز آرگومان دریافت کنند:
def changecase(n):
def decorator(func):
def myinner():
return func().upper() if n != 1 else func().lower()
return myinner
return decorator
@changecase(1)
def myfunction():
return "Hello Linus"
print(myfunction())
استفاده از چند دکوراتور
می توان چند دکوراتور را به ترتیب روی یک تابع اعمال کرد. ترتیب قرارگیری آن ها اهمیت دارد:
def changecase(func):
def myinner():
return func().upper()
return myinner
def addgreeting(func):
def myinner():
return "Hello " + func() + " Have a good day!"
return myinner
@changecase
@addgreeting
def myfunction():
return "Tobias"
print(myfunction())
حفظ اطلاعات متادیتا
زمانی که تابعی تزئین می شود، ویژگی هایی مانند __name__
تغییر می کند. برای جلوگیری از این مشکل از functools.wraps
استفاده می کنیم:
import functools
def changecase(func):
@functools.wraps(func)
def myinner():
return func().upper()
return myinner
@changecase
def myfunction():
return "Have a great day!"
print(myfunction.__name__)
ادامه یادگیری
برای یادگیری بیشتر درباره توابع در پایتون یا آشنایی با تابع range مطالعه کنید.