Closure

Closure تابعی است که مقادیر موجود در تابع در بر گیرنده خود را به خاطر می‌آورد، حتی اگر تابع در بر گیرنده از حافظه حذف شود. همانطور که در بخش توابع توضیح داده شد، می‌توان یک تابع را به عنوان آرگومان به تابع دیگر ارسال کرد:

 1 def functionA(myFunction):             
 2   return myFunction()
 3 
 4 def functionB():
 5     return "Hello World!";
 6 
 7 print("{0}".format(functionA(functionB)));
Hello World!

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

 1: def functionA(message):
 2:     def functionB():
 3:         print(message)
 4: 
 5:     return functionB
 6: 
 7: printMessage = functionA("Hello World!")
 8: 
 9: print(printMessage)
<function functionA.<locals>.functionB at 0x02300300>

همانطور که در کد بالا مشاهده می‌کنید ما یک تابع داریم (functionA) که در داخل آن یک تابع دیگر (functionB) قرار دارد. در خط 5 تابع ()functionA بدون پرانتز برگشت داده شده است. در خط 7 یک متغیر تعریف شده است که مقدار برگشتی از تابع ()functionA در آن قرار می‌گیرد. حال اگر مقدار این متغیر را چاپ کنیم (خط 9)، خروجی یک تابع را نشان می‌دهد که همان Closure است. حال خط 9 کد بالا، را به صورت زیر تغییر داده و برنامه را اجرا کنید :

printMessage()

بعد از اجرای برنامه، پیغام زیر چاپ می‌شود:

Hello World!

این خروجی نشان می‌دهد که تابع داخلی می‌تواند به متغیرهای تابعی که در آن قرار دارد، دسترسی داشته باشد. برای درک بهتر عملکرد Closuer ها به مثال زیر توجه کنید:

  1: def outter(number):
  2:     def inner(list):
  3:         return number in list
  4:     return inner
  5: 
  6: contains_15 = outter(15)
  7: 
  8: print(contains_15([1,2,3,4,5]))
  9: print(contains_15(range(1,20)))
False
True

در کد بالا یک تابع تعریف شده است (outter) که یک تابع را به عنوان خروجی برگشت می‌دهد (تابع inner). وظیفه تابع ()inner این است که آرگومانی که توسط تابع ()outter دریافت می‌شود را با یک لیست از اعداد مقایسه می‌کند، که آیا همچین عددی در داخل لیست است یا خیر؟ اگر وجود داشت، مقدار True و در غیر اینصورت مقدار False را بر می‌گرداند. همانطور که در خروجی مشاهده می‌کنید، برای لیست اول مقدار False و برای دومی مقدار True برگشت داده می‌شود. حال اگر در خط 7 کد بالا کد زیر را نوشته و برنامه را اجرا کنید، خروجی برنامه تغییر نمی‌کند:

del outter

یعنی با وجودیکه ما تابع اصلی را حذف کرده‌ایم، باز هم Closure وضعیت و خواسته ما از برنامه را می‌داند و کار خود را انجام می‌دهد. همان طور که در مثال‌های بالا مشاهده کردید، Closure زمانی به وجود می‌آید که یک تابع داخلی به مقداری در تابع دربرگیرنده‌اش ارجاع می‌دهد. شروطی که باید وجود داشته باشند تا یک Closure در پایتون ایجاد شود در زیر به صورت مختصر آورده شده است: