راه
۵ کیو· متوسط رو به بالامتوسطPYTHON۴ ثانیه · ۲۵۶ مگابایت

سنجایش

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


از شما خواسته می‌شود یک Decorator Factory (سازنده‌ی دکوراتور) با نام decorator_builder پیاده‌سازی کنید. این سازنده‌ی دکوراتور، خود به‌عنوان ورودی یک تابع اعتبارسنج (validator) دریافت می‌کند و سپس دکوراتوری را برمی‌گرداند که می‌تواند به توابع دیگر اعمال شود.


⚙️ عملکرد دکوراتور برگشتی

دکوراتور برگشتی باید عملکرد زیر را داشته باشد:

  1. دریافت ورودی‌ها: قبل از فراخوانی تابع اصلی (تابعی که دکوراتور به آن اعمال شده‌است)، ورودی‌های ارسالی به آن را دریافت کند.
  2. اعتبارسنجی: ورودی‌ها را به تابع validator که در زمان ساخت دکوراتور به decorator_builder داده شده بود، ارسال کند.
  3. بررسی نتیجه‌ی اعتبارسنجی: اگر تابع validator مقدار True برگرداند (یعنی ورودی‌ها معتبر باشند)، تابع اصلی را با همان ورودی‌ها فراخوانی کرده و نتیجه‌ی آن را برگرداند. اگر تابع validator مقدار False برگرداند (یعنی ورودی‌ها نامعتبر باشند)، تابع اصلی را فراخوانی نکرده و به جای آن، رشته‌ی 'error' را برگرداند.
  1. دریافت ورودی‌ها
  2. ارسال به validator
  3. True → اجرای تابع اصلی و برگرداندن نتیجه
  4. False → برگرداندن رشته‌ی 'error'

تابع validator ورودی‌های تابع اصلی را دریافت می‌کند و یک مقدار بولی برمی‌گرداند:

  • True: ورودی‌ها معتبر هستند.
  • False: ورودی‌ها نامعتبر هستند.

این تابع به سازنده‌ی دکوراتور شما ورودی داده می‌شود و وابسته به نوع تابعی است که قرار است دکوره شود. نیازی به پیاده‌سازی آن نیست.


🎯 مثال

در مثال زیر، یک validator برای بررسی مثبت یا صفر بودن عدد ورودی تعریف شده‌است. سپس با استفاده از decorator_builder و این validator، تابع square_root که ریشه‌ی دوم را حساب می‌کند، دکوره شده‌است:

python
def nonnegative_validator(x):
    return x >= 0


@decorator_builder(nonnegative_validator)
def square_root(x):
    return x ** 0.5


print(square_root(4))  # 2.0

print(square_root(-4)) # error

خروجی:

text
2.0
error
  • nonnegative_validator بررسی می‌کند که آیا x بزرگ‌تر یا مساوی صفر است.
  • برای 4 → True → تابع square_root اجرا می‌شود و خروجی 2.0 چاپ می‌شود.
  • برای -4 → False → تابع square_root اجرا نمی‌شود و رشته‌ی 'error' چاپ می‌شود.

🏗️ ساختار دکوراتور

ساختار کلی decorator_builder باید به شکل زیر باشد:

python
def decorator_builder(validator):
    """سازنده‌ی دکوراتور که یک تابع اعتبارسنج دریافت می‌کند"""

    def decorator(func):
        """دکوراتور واقعی که تابع اصلی را دریافت می‌کند"""

        def wrapper(*args, **kwargs):
            """تابع بسته‌بندی‌شده که اعتبارسنجی را انجام می‌دهد"""

            if validator(*args, **kwargs):
                return func(*args, **kwargs)
            else:
                return "error"

        return wrapper

    return decorator
  • لایه ۱ (Builder): decorator_builder(validator) ← دریافت تابع اعتبارسنج
  • لایه ۲ (Decorator): decorator(func) ← دریافت تابع اصلی
  • لایه ۳ (Wrapper): wrapper(*args, **kwargs) ← اجرای اعتبارسنجی و فراخوانی تابع اصلی در صورت معتبر بودن
  • استفاده از *args و **kwargs برای پشتیبانی از هر تعداد آرگومان موقعیتی و کلیدواژه‌ای

⚠️ نکات مهم

  • در این تمرین، نیازی به دریافت ورودی از کاربر یا چاپ خروجی در کنسول ندارید.
  • شما فقط باید تابع decorator_builder را پیاده‌سازی کنید.
  • تابع validator به‌عنوان آرگومان به decorator_builder داده می‌شود و شما باید آن را در دکوراتور خود استفاده کنید.
  • در صورت نامعتبر بودن ورودی‌ها، باید رشته‌ی 'error' را برگردانید (نه چاپ کنید).
  • در صورت معتبر بودن ورودی‌ها، باید نتیجه‌ی تابع اصلی را برگردانید.
  • نیازی به فراخوانی تابع در کد ارسالی نیست. سیستم به‌طور خودکار تابع شما را با ورودی‌های مختلف تست خواهد کرد.

✅ این تمرین را در ویرایشگر خود پیاده‌سازی کنید. به یاد داشته باشید که تابع decorator_builder باید یک دکوراتور برگرداند و خود دکوراتور نیز یک تابع بسته‌بندی‌شده را برگرداند.

نمونه‌ها

ورودی نمونه ۱
def nonnegative_validator(x):
    return x >= 0

@decorator_builder(nonnegative_validator)
def square_root(x):
    return x ** 0.5

square_root(4)
square_root(-4)
خروجی نمونه ۱
2.0
'error'
ورودی نمونه ۲
def both_positive(a, b):
    return a > 0 and b > 0

@decorator_builder(both_positive)
def divide(a, b):
    return a / b

divide(6, 3)
divide(6, -3)
divide(a=9, b=3)
خروجی نمونه ۲
2.0
'error'
3.0
ورودی نمونه ۳
calls = []

def never(x):
    return False

@decorator_builder(never)
def record(x):
    calls.append(x)
    return x

record(1)
calls
خروجی نمونه ۳
'error'
[]
ورودی نمونه ۴
@decorator_builder(lambda s: isinstance(s, str))
def shout(s):
    return s.upper()

shout("hi")
shout(5)
خروجی نمونه ۴
'HI'
'error'

برای نوشتن پاسخ و دریافت امتیاز، ابتدا وارد حساب شوید.

ورود