پیشنیاز درک دکوراتور: تابع بهعنوان مقدار
در پایتون، توابع شیء درجهیک (first-class object) هستند؛ یعنی میتوان آنها را در متغیر ذخیره کرد، بهعنوان آرگومان به تابع دیگر پاس داد یا از یک تابع بازگرداند. این ویژگی پایهی درک دکوراتورهاست.
def shout(text):
return text.upper()
def apply(func, value):
return func(value)
print(apply(shout, "hello")) # HELLOمیتوانیم یک تابع را از داخل تابع دیگر بازگردانیم و به همراه خود، محیط متغیرهای اطراف را نیز حفظ کند؛ به این ویژگی closure گفته میشود:
def make_multiplier(factor):
def multiplier(number):
return number * factor
return multiplier
double = make_multiplier(2)
triple = make_multiplier(3)
print(double(5)) # 10
print(triple(5)) # 15در این مثال، تابع درونی multiplier حتی پس از پایان اجرای make_multiplier، همچنان به مقدار factor دسترسی دارد. این دقیقاً همان مکانیزمی است که دکوراتورها بر پایهی آن ساخته میشوند و در درس بعد آن را بهطور کامل بررسی میکنیم.
نکتهی مهم این است که closure فقط مقدار متغیر را کپی نمیکند، بلکه به خود متغیر در محدودهی تابع بیرونی ارجاع میدهد. به همین دلیل اگر تابع بیرونی چند بار با آرگومانهای متفاوت فراخوانی شود، هر بار یک closure کاملاً مستقل با محیط متغیرهای مخصوص به خودش ساخته میشود، بدون اینکه closureهای مختلف روی مقدار یکدیگر تأثیر بگذارند. همین رفتار است که به توابع تولیدشده در مثال بالا (double و triple) اجازه میدهد کاملاً مستقل از هم رفتار کنند، حتی با اینکه هر دو از یک تابع سازنده ساخته شدهاند.