Closure (คลอเจอร์) คือฟังก์ชันที่ "จดจำ" สภาพแวดล้อม (enclosing scope) ที่มันถูกสร้างขึ้น — สามารถเข้าถึงตัวแปรจาก outer function ได้แม้ outer function จบการทำงานแล้ว
Nested Functions (ฟังก์ชันซ้อน)
ฟังก์ชันที่定义อยู่ในฟังก์ชันอื่น เรียกว่า Nested Function เข้าถึงตัวแปรของ outer scope ได้
def func_out():
print("This is outer function.")
def func_in():
print("This function is defined inside func_out.\nThis is a nested function.")
print("We can call nested function here.")
func_in()
print("Calling func_out.")
func_out()
ผลลัพธ์:
Calling func_out. This is outer function. We can call nested function here. This function is defined inside func_out. This is a nested function.
Closure: คืนค่า Nested Function
ถ้า outer function return nested function นested function นั้นจะกลายเป็น Closure
def closure_func(start):
def increment_by(inc):
return start + inc
return increment_by
closure1 = closure_func(9)
closure2 = closure_func(90)
print(f'closure1(3) = {closure1(3)}') # 12
print(f'closure2(3) = {closure2(3)}') # 93
ผลลัพธ์:
closure1(3) = 12 closure2(3) = 93
แม้ closure1 และ closure2 จะอ้างอิงฟังก์ชัน increment_by เดียวกัน แต่แต่ละตัว "จดจำ" ค่า start ที่ต่างกัน (9 และ 90)
ตรวจสอบ Closure ด้วย __closure__
ทุก closure มี attribute __closure__ เป็น tuple ของ cell objects ที่เก็บค่าตัวแปรที่ capture ไว้
def closure_func(start):
def increment_by(inc):
return start + inc
return increment_by
a = closure_func(9)
b = closure_func(90)
print(f'type(a) = {type(a)}')
print(f'a.__closure__ = {a.__closure__}')
print(f'type(a.__closure__[0]) = {type(a.__closure__[0])}')
print(f'a.__closure__[0].cell_contents = {a.__closure__[0].cell_contents}')
print(f'type(b) = {type(b)}')
print(f'b.__closure__ = {b.__closure__}')
print(f'b.__closure__[0].cell_contents = {b.__closure__[0].cell_contents}')
ผลลัพธ์:
type(a) =a.__closure__ = ( ,) type(a.__closure__[0]) = | a.__closure__[0].cell_contents = 9 type(b) = b.__closure__ = ( ,) b.__closure__[0].cell_contents = 90 |
Closure vs Class
| Closure | Class |
|---|---|
| Syntax เรียบง่าย สำหรับ state 简单 | เหมาะสำหรับ state ซับซ้อน หลายเมธอด |
| Implicit state (เก็บใน __closure__) | Explicit state (self.attribute) |
| Immutable captured variables (Python 3) | Mutable attributes |
| ใช้ nonlocal เพื่อแก้ไข captured var | แก้ไข self.attr ได้โดยตรง |
การแก้ไข Captured Variable: nonlocal
Python 3 ใช้ nonlocal เพื่อบอกว่า variable ไมใช่ local แต่เป็นของ enclosing scope
def counter():
count = 0
def increment():
nonlocal count
count += 1
return count
return increment
c = counter()
print(c()) # 1
print(c()) # 2
print(c()) # 3
Use Cases ของ Closure
- Function Factories: สร้างฟังก์ชันเฉพาะงาน (เช่น multiplier, validator)
- Decorators: Decorator พื้นฐานคือ closure
- Callbacks/Event Handlers: เก็บ context ไว้
- Memoization/Caching: จดจำผลลัพธ์ (เช่น fibonacci)
- Partial Application: คงค่าบางอาร์กิวเมนต์ไว้
ตัวอย่าง: Function Factory
def make_multiplier(factor):
def multiply(x):
return x * factor
return multiply
double = make_multiplier(2)
triple = make_multiplier(3)
print(double(5)) # 10
print(triple(5)) # 15
ตัวอย่าง: Memoization Decorator
def memoize(func):
cache = {}
def wrapper(*args):
if args not in cache:
cache[args] = func(*args)
return cache[args]
return wrapper
@memoize
def fib(n):
if n < 2:
return 1
return fib(n-1) + fib(n-2)
print(fib(30)) # เร็วมากเพราะ cache
สรุป
- Closure = Nested function ที่ถูก return และจดจำ enclosing scope
- ตรวจสอบได้ด้วย
func.__closure__และcell_contents - ใช้
nonlocalเพื่อ modify captured variable - ประยุกต์ใช้กับ Decorators, Factories, Callbacks, Caching