سنجایش
همانطور که میدانید، برخی توابع تنها برای دامنهی خاصی از ورودیها تعریف شدهاند و برای ورودیهای خارج از آن دامنه، یا خطایی رخ میدهد یا نتیجهی معتبری ندارند. بهعنوان مثال، تابع ریشهی دوم (رادیکال) برای اعداد منفی در مجموعهی اعداد حقیقی تعریفنشده است. مدیریت این موارد میتواند کد تابع اصلی را شلوغ کند. دکوراتورها راهی عالی برای افزودن قابلیتهای جانبی (مانند اعتبارسنجی) به توابع، بدون تغییر کد اصلی آنها، ارائه میدهند.
از شما خواسته میشود یک Decorator Factory (سازندهی دکوراتور) با نام
decorator_builderپیادهسازی کنید. این سازندهی دکوراتور، خود بهعنوان ورودی یک تابع اعتبارسنج (validator) دریافت میکند و سپس دکوراتوری را برمیگرداند که میتواند به توابع دیگر اعمال شود.
⚙️ عملکرد دکوراتور برگشتی
دکوراتور برگشتی باید عملکرد زیر را داشته باشد:
- دریافت ورودیها: قبل از فراخوانی تابع اصلی (تابعی که دکوراتور به آن اعمال شدهاست)، ورودیهای ارسالی به آن را دریافت کند.
- اعتبارسنجی: ورودیها را به تابع
validatorکه در زمان ساخت دکوراتور بهdecorator_builderداده شده بود، ارسال کند. - بررسی نتیجهی اعتبارسنجی: اگر تابع
validatorمقدارTrueبرگرداند (یعنی ورودیها معتبر باشند)، تابع اصلی را با همان ورودیها فراخوانی کرده و نتیجهی آن را برگرداند. اگر تابعvalidatorمقدارFalseبرگرداند (یعنی ورودیها نامعتبر باشند)، تابع اصلی را فراخوانی نکرده و به جای آن، رشتهی'error'را برگرداند.
- دریافت ورودیها
- ارسال به
validator- True → اجرای تابع اصلی و برگرداندن نتیجه
- False → برگرداندن رشتهی
'error'
تابع
validatorورودیهای تابع اصلی را دریافت میکند و یک مقدار بولی برمیگرداند:
True: ورودیها معتبر هستند.False: ورودیها نامعتبر هستند.این تابع به سازندهی دکوراتور شما ورودی داده میشود و وابسته به نوع تابعی است که قرار است دکوره شود. نیازی به پیادهسازی آن نیست.
🎯 مثال
در مثال زیر، یک validator برای بررسی مثبت یا صفر بودن عدد ورودی تعریف شدهاست. سپس با استفاده از decorator_builder و این validator، تابع square_root که ریشهی دوم را حساب میکند، دکوره شدهاست:
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
خروجی:
2.0
error
nonnegative_validatorبررسی میکند که آیاxبزرگتر یا مساوی صفر است.- برای
4→True→ تابعsquare_rootاجرا میشود و خروجی2.0چاپ میشود.- برای
-4→False→ تابعsquare_rootاجرا نمیشود و رشتهی'error'چاپ میشود.
🏗️ ساختار دکوراتور
ساختار کلی decorator_builder باید به شکل زیر باشد:
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'
برای نوشتن پاسخ و دریافت امتیاز، ابتدا وارد حساب شوید.
ورود