آموزش decorator در پایتون به زبان ساده
دکوراتورها (decorator) یکی از ویژگیهای قدرتمند زبان برنامهنویسی پایتون هستند که به شما امکان میدهند رفتار توابع را تغییر یا بهبود دهید. میتوان از آنها برای افزودن عملکرد جدید به کد موجود بدون تغییر پیادهسازی اساسی استفاده کرد. در این نوشتار از مکتوب، مفهوم decorator در پایتون و ابعاد مختلف آن را بررسی کرده و مثالهایی ارائه خواهیم کرد تا به شما در درک نحوه استفاده مؤثر از آنها کمک کنیم.
decorator در پایتون چیست؟
decorator در پایتون (decorator in python) در اصل نوعی تابع مرتبه بالاتر است که یک تابع پایتون (python function) را به عنوان آرگومان (همچنین به عنوان پارامتر نیز از آن نام میبرند) میگیرد و یک تابع جدید را با رفتار اصلاح شده برمیگرداند. دکوراتورها برای افزودن قابلیت به تابع یا عملکردی موجود یا تغییر رفتار آن استفاده میشوند. آنها معمولاً برای کارهایی مانند ورود به سیستم، زمانبندی و احراز هویت استفاده مورداستفاده قرار میگیرند. دکوراتورها در پایتون با استفاده از نماد “@” برای توابع اعمال میشوند. سینتکس آن به صورت زیر است:
@my_decorator
def my_function():
pass
در این مثال، تابع my_decorator با استفاده از دستور decorator به تابع my_function اعمال میشود. تابع my_decorator تابع my_function را به عنوان آرگومان میگیرد و یک تابع جدید با رفتار اصلاح شده برمیگرداند.
پیشنهاد مطالعه: کتابخانه های پایتون + مزایا، معایب و کاربرد هرکدام
ایجاد decorator در پایتون
برای ایجاد decorator در پایتون (decorator in python)، تابعی را تعریف میکنیم که تابع دیگری را به عنوان آرگومان میگیرد، حال این دکوراتور در پایتون آن را به نحوی اصلاح میکند و تابع تغییر یافته را برمیگرداند. به مثال زیر در این رابطه توجه کنید:
def my_decorator(func):
def wrapper():
print("قبل از فراخوانی تابع")
func()
print("بعد از فراخوانی تابع")
return wrapper
در مثال فوق، تابع my_decorator تابع دیگری، func را به عنوان آرگومان میگیرد. تابع جدیدی به نام wrapper تعریف میکند که رفتار تابع func را با چاپ یک پیام قبل و بعد از فراخوانی تابع تغییر میدهد.
برای اعمال تابع my_decorator به یک تابع دیگر، به سادگی از دستور decorator به صورت زیر باید استفاده کنیم.
@my_decorator
def my_function():
print("سلام. به مجله مکتب خونه خوش آمدید")
وقتی my_function را فراخوانی میکنیم، تابع my_decorator به آن اعمال میشود و تابع تغییر یافته فراخوانی میشود:
my_function():
خروجی با فراخوانی تابع فوق به صورت زیر خواهد بود:
انتقال آرگومان به دکوراتور
گاهی اوقات لازم است آرگومانها (arguments) را به یک دکوراتور منتقل کنیم. برای انجام این کار، میتوانیم یک تابع دکوراتور (decorated function) تعریف کرده که آرگومانها را میگیرد و سپس یک تابع تودرتو تعریف کنیم که تابعی را که قرار است اصلاح شود، به عنوان آرگومان میگیرد. مثال زیر برای درک این موضوع بسیار مهم است:
def repeat(num):
def my_decorator(func):
def wrapper():
for i in range(num):
func()
return wrapper
return my_decorator
@repeat(num=3)
def say_hello():
print("سلام. به مجله مکتب خونه خوش آمدید")
در مثال فوق، تابع repeat یک آرگومان num میگیرد و یک تابع decorator را برمیگرداند که تابع دیگری، func را به عنوان آرگومان میگیرد. تابع wrapper برای تکرار تابع func تعداد دفعات تعریف شده است. در نهایت، دکوراتور با استفاده از دستور decorator به تابع say_hello اعمال میشود. وقتی تابع say_hello را فراخوانی میکنیم، در اصل سه بار فراخوانی میشود که خروجی به صورت زیر خواهد بود:
دکوراتور کلاس پایتون چیست؟
در پایتون، دکوراتورهای کلاس (python class decorator) شبیه دکوراتورهای تابع (decorator function) هستند، اما به جای توابع، روی کلاسها اعمال میشوند. دکوراتورهای کلاس در پایتون، توابع درجه بالاتری هستند که یک کلاس را به عنوان ورودی میگیرند و یک کلاس جدید را با رفتار اصلاح شده برمیگردانند.
در اینجا یک مثال از یک کلاس دکوراتور در پایتون (python decorator example) آمده است:
def add_method(cls):
def new_method(self, value):
self.value = value
cls.new_method = new_method
return cls
@add_method
class MyClass:
def __init__(self):
self.value = 0
my_object = MyClass()
my_object.new_method(5)
print(my_object.value)
خروجی به صورت زیر خواهد بود:
در مثال فوق، یک کلاس decorator add_method تعریف میکنیم که یک کلاس cls را به عنوان ورودی میگیرد و یک متد جدید new_method را به کلاس اضافه میکند. متد new_method یک مقدار آرگومان میگیرد و ویژگی ارزش شی را به مقدار داده شده تنظیم میکند.
سپس با استفاده از دستور @add_method decorator add_method را به کلاس MyClass اعمال میکنیم. این رفتار کلاس MyClass را با اضافه کردن متد new_method به آن تغییر میدهد. در نهایت، یک نمونه از کلاس MyClass ایجاد میکنیم و متد new_method را با آرگومان 5 فراخوانی خواهیم کرد. این ویژگی ارزش شی را 5 میکند.
پیشنهاد مطالعه: آموزش کار با پایتون در اندروید
کاربرد decorator در پایتون چیست؟
decorator در پایتون برای اصلاح رفتار توابع یا کلاسها استفاده میشوند. آنها توابع درجه بالاتری هستند که تابع یا کلاس را به عنوان ورودی میگیرند و تابع یا کلاسی جدید را با رفتار اصلاح شده برمیگردانند. دکوراتورها معمولاً برای افزودن عملکردهای جدید به کدهای موجود بدون تغییر در پیادهسازی زیربنایی استفاده میشوند و کد را قابلاستفادهتر و ماژولارتر میکنند.
در اینجا چند کاربرد متداول دکوراتورها در پایتون آورده شده است:
- ورود به سیستم: میتوانیم از دکوراتورها برای افزودن قابلیت ثبت به عملکردها یا کلاسها استفاده کنید. این عمل به ما امکان میدهد اطلاعات مهمی مانند نام تابع، آرگومانها و مقادیر بازگشتی را ثبت کنیم.
- زمانبندی: از دکوراتورها میتوان برای زمانبندی اجرای عملکردها یا توابع استفاده کرد. این کار برای تجزیهوتحلیل عملکرد و بهینهسازی کد بسیار مفید است.
- ذخیرهسازی: میتوانیم از دکوراتورها برای ذخیره کردن نتایج یک تابع استفاده کنیم، به طوری که اگر تابع دوباره با همان آرگومانها فراخوانی شود، به جای محاسبه مجدد نتیجه، نتیجه ذخیره شده در حافظه پنهان برگردانده میشود.
- احراز هویت: از دکوراتورها میتوان برای افزودن قابلیت احراز هویت به توابع یا کلاسها استفاده کرد. این کار تضمین میکند که فقط کاربران مجاز میتوانند به بخشهای خاصی از کد دسترسی داشته باشند.
- مدیریت خطا: میتوانیم از دکوراتورها برای اضافه کردن عملکرد مدیریت خطا به عملکردها یا کلاسها استفاده کنیم. این به ما امکان میدهد استثناهایی را که توسط تابع یا کلاس ایجاد میشوند، بگیریم و مدیریت کنیم.
به طور کلی، decorator در پایتون یک ویژگی قدرتمند و همهکاره محسوب میشود که میتواند برای بهبود عملکرد و ماژولار بودن کد ما استفاده شود.
پیشنهاد مطالعه: آموزش classmethod در پایتون به زبان ساده + مثال عملی
مزایای استفاده از دکوراتور در پایتون چیست؟
استفاده از دکوراتورها در پایتون چندین مزیت دارد که مهمترین آنها به صورت موارد زیر هستند:
- قابلیت استفاده مجدد کد: دکوراتورها به ما این امکان را میدهند که بدون تغییر پیادهسازی اساسی، عملکرد جدیدی به کد موجود اضافه کنیم. این باعث میشود کد قابل استفاده مجدد و ماژولارتر باشد.
- بهبود خوانایی و عملکرد کد: دکوراتورها به ما این امکان را میدهند که نگرانیهای مقطعی مانند ورود به سیستم، احراز هویت و حافظه پنهان را از عملکرد اصلی کد خود جدا کنیم. این قابلیت نگهداری و خوانایی کد ما را بهبود میبخشد.
- انعطافپذیری: از decorator در پایتون میتوان برای تغییر رفتار توابع یا کلاسها در زمان اجرا، بر اساس زمینهای که در آن استفاده میشود، استفاده کرد. این انعطافپذیری زیادی را فراهم میکند و به ما امکان میدهد کد پویاتر و سازگارتر ایجاد کنیم.
- بهبود خوانایی کد: دکوراتورها میتوانند به خوانایی بیشتر کد کمک کنند و به ما امکان میدهند عملکردهای پیچیده را به دکوراتورهای ساده و قابلفهم تبدیل کنیم.
- صرفهجویی در زمان: با استفاده از دکوراتورها در پایتون، میتوانیم از تکرار کد جلوگیری کرده و با استفاده مجدد از عملکرد موجود در زمان صرفهجویی کنیم.
- پیادهسازی آسان: پیادهسازی دکوراتورها در پایتون آسان است. این باعث میشود به شکلی راحت در صورت نیاز، دکوراتورهای جدید را به کد خود اضافه کنیم.
به طور کلی، دکوراتورها یکی از ویژگیهای قدرتمند پایتون هستند که مزایای زیادی را برای ایجاد کد قابل استفاده مجدد، ماژولار و قابل نگهداری ارائه میدهند.
پیشنهاد مطالعه: آموزش دستورات شرطی در پایتون به زبان ساده
مثالی از دکوراتور در پایتون
در اینجا یک مثال کاربردی از نحوه استفاده از decorator در پایتون آورده شده است که در ادامه این مثال پایتون (python example) را کاملاً تشریح خواهیم کرد.
import logging
logging.basicConfig(filename='example.log', level=logging.INFO)
def log_function_call(func):
def wrapper(*args, **kwargs):
logging.info(f"Function {func.__name__} called with arguments {args}, {kwargs}")
return func(*args, **kwargs)
return wrapper
@log_function_call
def add_numbers(a, b):
return a + b
result = add_numbers(2, 3)
print(result)
خروجی کد بالا به صورت زیر است:
در مثال فوق، ما یک دکوراتور log_function_call تعریف میکنیم که تابعی را به عنوان ورودی میگیرد و یک تابع جدید را برمیگرداند که اطلاعات مربوط به فراخوانی تابع را قبل از فراخوانی تابع اصلی ثبت میکند. تابع wrapper هر تعداد آرگومان args و آرگومانهای کلیدواژه kwargs (args kwargs) را با استفاده از دستور *args و **kwargs میگیرد.
سپس از دستور decorator @log_function_call برای اعمال دکوراتور log_function_call در تابع add_numbers استفاده میکنیم. این به این معنی است که وقتی add_numbers را فراخوانی میکنیم، به جای آن دکوراتور log_function_call فراخوانی میشود و تابع اصلی از داخل دکوراتور فراخوانی میشود.
در نهایت تابع add_numbers را با آرگومانهای 2 و 3 فراخوانی میکنیم و نتیجه 5 برمیگردد. Decorator اطلاعات مربوط به فراخوانی تابع را در فایلی به نام example.log در سطح INFO ثبت میکند که شامل نام تابع و آرگومانهایی خواهد بود که به آن ارسال شده است.
با استفاده از decorator در پایتون میتوانیم به راحتی با اعمال دکوراتور به هر عملکردی قابلیت ثبت را اضافه کنیم. Decorate در پایتون به ما این امکان را میدهد که نگرانی ورود به سیستم را از عملکرد اصلی تابع جدا کنیم و ماژولار بودن و قابلیت نگهداری کد خود را بهبود ببخشیم.
پیشنهاد مطالعه: کتابخانه های پایتون + مزایا، معایب و کاربرد هرکدام
سخن پایانی
در این مقاله به بررسی و آموزش decorator در پایتون و نحوه استفاده از آنها برای اصلاح یا بهبود رفتار توابع پرداختهایم. ما نحوه ایجاد دکوراتور، نحوه استفاده از نحو دکوراتور و نحوه انتقال آرگومانها به دکوراتور را بررسی کردیم و مزایا و کاربردهای دکوراتور در پایتون را مورد بحث قرار دادیم. امیدوارم که این مطلب در مورد decorating در پایتون برای شما مفید واقع شده باشد.
یادگیری آسان پایتون
اگر به فکر یادگیری پایتون به آسانترین شکل ممکن هستید و دوست دارید در زمینه برنامهنویسی پایتون پیشرفت کنید، ما به شما دورههای آموزش پایتون مکتب خونه را توصیه میکنیم. دورههای موجود پایتون در مکتب خونه به وسیله اساتید مجرب تهیه و تدوین شدهاند و به شما در یادگیری پایتون بسیار کمک خواهند کرد.