یک تابع خوب مشخص میکنه چه ورودیای میگیره و چه نتیجهای میده. print فقط چیزی نشان میده؛ return نتیجه رو به بخشی که تابع رو صدا زده میده تا در کار بعدی استفاده کند. تابعی که به انتها برسد و return نداشته باشه، None برمیگردونه.
در مثال، rate پیشفرض داره و اختیاری هست. با نام پارامتر هم میشه آرگومان داد: rate=0.2 قصد ما رو روشن میکنه. اسمهایی که داخل تابع تعریف میکنی، معمولاً فقط همونجا در دسترس هستن؛ برای انتقال نتیجه بهتره از return استفاده کنیم.
bounds چند نتیجه میده؛ این نتایج در واقع یک تاپلاند که در low و high باز میشه. برای ورودی خالی None داریم، پس پیش از باز کردن باید وجود نتیجه رو بررسی کنیم.
from functools import wraps
def price_with_tax(price, rate=0.1):
return price * (1 + rate)
def bounds(values):
if not values:
return None
return min(values), max(values)
def nonnegative(function):
@wraps(function)
def wrapper(value):
if value < 0:
return None
return function(value)
return wrapper
@nonnegative
def double(value):
return value * 2
print(price_with_tax(100))
print(price_with_tax(100, rate=0.2))
low, high = bounds([7, 2, 9])
print(low, high)
print(double(3))
print(double(-1))
print(double.__name__)
خود تابع هم یک مقدار هست: میشه اون رو به تابع دیگر داد یا از تابع برگرداند. دکوراتور (decorator) یک تابع رو میگیره و تابعی تازه به جاش میده تا کاری به رفتار قبلی اضافه کنه. به این تابع تازه معمولاً wrapper میگیم. wrapper در این مثال ورودی منفی رو رد میکنه و ورودی معتبر رو به تابع اصلی میده.
نوشتن @nonnegative تقریباً همون double = nonnegative(double) هست. wraps نام و توضیح تابع اصلی رو نگه میدارد. دستور from functools import wraps فقط ابزار آمادهٔ کتابخانهٔ استاندارد رو در اختیارمان میذاره؛ ساختن فایل و ماژول جدا در دورهٔ بعد هست.
سه لحظه رو جدا ببین: ساخت تابع اصلی؛ ساخت wrapper؛ اجرای wrapper وقتی تابع صدا زده میشه. function در محیط تابع بیرونی باقی میمونه و wrapper اون رو به خاطر میسپارد؛ این به خاطر سپردن متغیرهای تابع بیرونی رو closure مینامیم.
سه ابزار آماده برای دنبالهٔ عددها: min کمترین، max بیشترین و sum مجموع رو میده. min و max روی فهرست خالی بدون مقدار پیشفرض خطا دارن؛ به همین دلیل در bounds ابتدا خالی بودن رو بررسی کردیم.
فعالیت شما
پیشفرض، آرگومان نامدار، None، خروجی چندتایی و decorator رو دنبال کن.