Weak Reference อ้างอิง Object แต่ ไม่เพิ่ม Reference Count Object ถูก Garbage Collect ได้ปกติ เหมาะสำหรับ Cache, Observer Pattern, Circular Reference Prevention
import weakref
คลาสและฟังก์ชันหลัก
| Class/Function | คำอธิบาย |
|---|---|
weakref.ref(obj[, callback]) | สร้าง Weak Reference เรียก ref() ได้ Object (หรือ None ถ้าถูก GC) |
weakref.proxy(obj[, callback]) | สร้าง Proxy Object ใช้งานเหมือน Object จริง แต่อย่าง Weak |
weakref.getweakrefcount(obj) | นับ Weak References + Proxies |
weakref.getweakrefs(obj) | List ของ Weak References + Proxies |
weakref.finalize(obj, func, *args, **kwargs) | ลงทะเบียน Callback ตอน Object ถูก GC (3.4+) |
โค้ดตัวอย่าง
import weakref
class MyList(list):
pass
obj = MyList('String') # ['S', 't', 'r', 'i', 'n', 'g']
# Weak Reference
weak_ref = weakref.ref(obj)
print(weak_ref()) # ['S', 't', 'r', 'i', 'n', 'g']
# Proxy
proxy = weakref.proxy(obj)
print(proxy) # ['S', 't', 'r', 'i', 'n', 'g']
# Reference Count
print(weakref.getweakrefcount(obj)) # 2
# ลบ Original
del obj
print(weak_ref()) # None (Object ถูก GC แล้ว)
# Proxy หลัง GC -> ReferenceError
try:
print(proxy)
except ReferenceError:
print("Proxy: Object gone!")
ผลลัพธ์
['S', 't', 'r', 'i', 'n', 'g'] ['S', 't', 'r', 'i', 'n', 'g'] 2 None Proxy: Object gone!
Callback on Deletion
import weakref
def cleanup(ref):
print(f"Object {ref} has been garbage collected!")
obj = MyList('data')
ref = weakref.ref(obj, cleanup)
del obj
# Output: Object has been garbage collected!
finalize() - ทันสมัยกว่า (Python 3.4+)
import weakref
class Resource:
def __init__(self, name):
self.name = name
def close(self):
print(f"Closing {self.name}")
res = Resource("DB Connection")
finalizer = weakref.finalize(res, res.close)
print(finalizer.alive) # True
del res
print(finalizer.alive) # False
# Output: Closing DB Connection
Objects ที่ไม่รองรับ Weak Reference
- Built-in Types:
int, float, str, tuple, bytes, frozenset - Built-in Functions/Methods
- Classes ที่ Define
__slots__โดยไม่มี'__weakref__'
Use Cases จริง
1. Cache (ไม่ป้องกัน GC)
import weakref
class Cache:
def __init__(self):
self._cache = weakref.WeakValueDictionary()
def get(self, key, factory):
if key not in self._cache:
self._cache[key] = factory(key)
return self._cache[key]
# ใช้งาน
cache = Cache()
data = cache.get('user:1', lambda k: fetch_user(k))
# ถ้า data ไม่ถูกใช้ที่อื่น -> GC ได้อัตโนมัติ
2. Observer Pattern
class Subject:
def __init__(self):
self._observers = weakref.WeakSet()
def register(self, observer):
self._observers.add(observer)
def notify(self, event):
for obs in self._observers:
obs.update(event)
3. Circular Reference Prevention
class Node:
def __init__(self, value):
self.value = value
self.parent = None
self.children = []
def add_child(self, child):
self.children.append(child)
child.parent = weakref.ref(self) # Weak Ref ป้องกัน Cycle
Weak Containers
WeakValueDictionary- Key=Strong, Value=WeakWeakKeyDictionary- Key=Weak, Value=StrongWeakSet- Elements=WeakWeakMethod- Weak Reference to Bound Method (3.4+)