خانه / آموزش‌ها / آموزش دکوراتورها در پایتون (Decorators)

آموزش دکوراتورها در پایتون (Decorators)

🐍 HomeOfPython
|
📅 1404/10/18

سطح مقدماتی (Beginner Level)

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

قبل از درک دکوراتورها، باید سه مفهوم کلیدی را در پایتون درک کنید:

  1. توابع به عنوان اشیاء (First-Class Objects).
  2. توابع تو در تو (Nested Functions).
  3. بازگرداندن یک تابع از تابع دیگر.

۱. توابع به عنوان اشیاء

در پایتون، همه چیز شیء است. این یعنی می‌توانید یک تابع را درون یک متغیر ذخیره کنید یا آن را به عنوان ورودی به تابع دیگری بدهید.

Python

۲. مفهوم دکوراتور ساده

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

فرض کنید می‌خواهیم قبل از اجرای هر تابع، یک پیام خوش‌آمدگویی چاپ کنیم:

Python

۳. استفاده از سینتکس @

پایتون برای راحت‌تر کردن کار، سینتکس @ (Pie Syntax) را معرفی کرده است. کد زیر دقیقا همان کار مثال بالا را انجام می‌دهد اما تمیزتر است.

نحوه عملکرد دکوراتور

Python

سطح پیشرفته (Professional Level)

در پروژه‌های واقعی و فریم‌ورک‌هایی مثل Django یا Flask، دکوراتورها بسیار پیچیده‌تر هستند. در این سطح یاد می‌گیریم چطور دکوراتورهایی بنویسیم که آرگومان می‌پذیرند، یا دکوراتورهایی که متا-دیتای تابع اصلی را حفظ می‌کنند.

۱. دکوراتور برای توابع دارای آرگومان

اگر تابعی که دکوریت می‌شود ورودی داشته باشد، تابع داخلی (wrapper) هم باید آن ورودی‌ها را بپذیرد. بهترین روش استفاده از *args و **kwargs است تا دکوراتور ما عمومی باشد.

Python

۲. مشکل نام تابع و functools.wraps

وقتی از دکوراتور استفاده می‌کنید، نام تابع اصلی و توضیحات (Docstring) آن با تابع wrapper جایگزین می‌شود. برای دیباگ کردن این یک فاجعه است. ماژول functools این مشکل را حل می‌کند.

به تفاوت __name__ در کد زیر دقت کنید:

Python

۳. دکوراتورهای پارامتردار (Nested Decorators)

گاهی خود دکوراتور نیاز به تنظیمات دارد. مثلاً @retry(times=3). برای این کار باید سه لایه تابع تو در تو داشته باشیم.

Python

۴. مثال کاربردی: اندازه‌گیری زمان اجرا (Timing)

یکی از رایج‌ترین کاربردهای دکوراتور، محاسبه زمان اجرای الگوریتم‌هاست.

python
# Static Snippet: Timing logic blueprint
import time

def timer(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"زمان اجرا: {end - start} ثانیه")
        return result
    return wrapper
Python

۵. دکوراتورهای کلاس (Class Decorators)

علاوه بر توابع، می‌توانیم کلاس‌ها را هم دکوریت کنیم یا حتی از کلاس به عنوان دکوراتور استفاده کنیم (با پیاده‌سازی متد __call__).

Python