Ei vielä käännetty
Tätä sivua ei ole vielä käännetty suomeksi, joten se näytetään englanniksi. Auta kääntämään
weakref Module¶
The weakref module provides utilities for creating weak references to objects, allowing garbage collection when objects are no longer strongly referenced.
Complexity Reference¶
| Operation | Time | Space | Notes |
|---|---|---|---|
ref(obj) |
O(1) | O(1) | Create weak reference |
proxy(obj) |
O(1) | O(1) | Create proxy object |
getweakrefcount(obj) |
O(1) | O(1) | Count weak refs |
getweakrefs(obj) |
O(n) | O(n) | n = weak refs |
WeakKeyDictionary operations |
O(1) avg | O(n) | n = entries; O(n) worst case due to hash collisions |
WeakValueDictionary operations |
O(1) avg | O(n) | n = entries; O(n) worst case due to hash collisions |
Common Operations¶
Creating Weak References¶
import weakref
class MyClass:
pass
obj = MyClass()
# O(1) - create weak reference
weak_ref = weakref.ref(obj)
# O(1) - dereference (get original object)
original = weak_ref()
if original is not None:
print("Object still exists")
else:
print("Object was garbage collected")
# When obj is deleted, weak_ref() returns None
del obj
print(weak_ref()) # None
Creating Proxies¶
import weakref
class MyClass:
def method(self):
return "Hello"
obj = MyClass()
# O(1) - create proxy
proxy = weakref.proxy(obj)
# Use like the original object
result = proxy.method() # O(1) lookup + O(n) method execution
# After deletion, proxy raises ReferenceError
del obj
try:
proxy.method() # Raises ReferenceError
except ReferenceError:
print("Object was garbage collected")
Callbacks on Object Deletion¶
import weakref
class Resource:
def __init__(self, name):
self.name = name
def cleanup_callback(weak_ref):
"""Called when object is garbage collected - O(1)"""
print("Resource was cleaned up!")
resource = Resource("data.txt")
# O(1) - create reference with callback
weak_ref = weakref.ref(resource, cleanup_callback)
# When resource is deleted, callback is invoked - O(1)
del resource # Prints: "Resource was cleaned up!"
Common Use Cases¶
Caching with Automatic Cleanup¶
import weakref
class CachedResource:
"""Cache that auto-cleans when objects are GC'd"""
def __init__(self):
self._cache = weakref.WeakValueDictionary()
def register(self, key, obj):
"""O(1) - add to cache"""
self._cache[key] = obj
def get(self, key):
"""O(1) - retrieve from cache"""
return self._cache.get(key)
def size(self):
"""O(1) - active entries only"""
# Dead entries auto-removed during iteration
return len(self._cache)
# Usage
cache = CachedResource()
class Data:
def __init__(self, value):
self.value = value
obj1 = Data("value")
cache.register("key1", obj1)
retrieved = cache.get("key1") # O(1)
print(retrieved) # {"data": "value"}
del obj1
print(cache.size()) # obj1 auto-removed - O(1)
Observing Object Lifecycle¶
import weakref
class LifecycleObserver:
"""Track object creation and destruction"""
def __init__(self):
self._objects = {}
self._count = 0
def register(self, obj):
"""O(1) - track object"""
obj_id = id(obj)
def on_delete(ref):
del self._objects[obj_id]
self._count -= 1
weak_ref = weakref.ref(obj, on_delete)
self._objects[obj_id] = weak_ref
self._count += 1
return self._count
def alive_count(self):
"""O(1) - count alive objects"""
return self._count
# Usage
observer = LifecycleObserver()
obj1 = [1, 2, 3]
obj2 = [4, 5, 6]
observer.register(obj1) # O(1)
observer.register(obj2) # O(1)
print(observer.alive_count()) # 2
del obj1
print(observer.alive_count()) # 1
Circular Reference Prevention¶
import weakref
class Parent:
def __init__(self, name):
self.name = name
self.children = []
def add_child(self, child):
self.children.append(child)
child.parent = weakref.ref(self) # O(1) - weak reference
class Child:
def __init__(self, name):
self.name = name
self.parent = None # Will be weakref
def get_parent(self):
"""O(1) - dereference weak ref"""
if self.parent is None:
return None
parent = self.parent()
if parent is None:
print("Parent was garbage collected")
return parent
# No circular reference!
parent = Parent("Dad")
child = Child("Son")
parent.add_child(child) # O(1)
print(child.get_parent().name) # O(1) dereference
del parent
print(child.get_parent()) # None (parent deleted)
Registry Pattern¶
import weakref
class Registry:
"""Register objects and query them later - O(1) add/remove"""
def __init__(self):
self._registry = weakref.WeakSet()
def register(self, obj):
"""O(1) - add to registry"""
self._registry.add(obj)
def count(self):
"""O(n) - count active objects where n = registered"""
# Dead objects auto-removed
return len(self._registry)
def iterate_active(self):
"""O(n) - iterate only live objects"""
for obj in self._registry:
yield obj
# Usage
registry = Registry()
obj1 = Data(1)
obj2 = Data(2)
obj3 = Data(3)
registry.register(obj1) # O(1)
registry.register(obj2) # O(1)
registry.register(obj3) # O(1)
print(f"Registered: {registry.count()}") # O(1) = 3
del obj2
print(f"Registered: {registry.count()}") # O(1) = 2
for obj in registry.iterate_active(): # O(n) = 2 iterations
print(obj)
Performance Tips¶
Use WeakKeyDictionary for Object-Based Keys¶
import weakref
# Bad: Strong references keep objects alive
strong_cache = {}
# Good: Weak references allow GC
weak_cache = weakref.WeakKeyDictionary()
class Key:
pass
key = Key()
weak_cache[key] = "value" # O(1)
# Object can be GC'd even with key in dict
del key
print(len(weak_cache)) # 0 - auto-cleaned
Cache Query Without Keeping References¶
import weakref
class TransientCache:
"""Query cache without holding references"""
def __init__(self):
self._cache = weakref.WeakValueDictionary()
def query(self, key):
"""O(1) - may return None if GC'd"""
return self._cache.get(key)
def query_exists(self, key):
"""O(1) - check existence without strong ref"""
return key in self._cache
# Usage
cache = TransientCache()
obj = Data("value")
cache._cache["key"] = obj # O(1)
# Query without keeping obj alive
data = cache.query("key") # O(1)
# obj might be GC'd here
exists = cache.query_exists("key") # O(1) - won't prevent GC
Related Documentation¶
- gc Module - Garbage collection control
- Collections Module - OrderedDict alternatives