Weak References with weakref
Scorri per mostrare il menu
A normal reference keeps an object alive by incrementing its reference count. A weak reference points to an object without incrementing its count – the object can be garbage collected even while a weak reference to it exists. This is the standard tool for caches and observer patterns where you don't want references to prevent cleanup.
The Problem Weak References Solve
A cache that holds strong references to its values keeps those values alive indefinitely – even if nothing else in the program needs them:
12345678910111213141516171819202122232425import sys # Strong reference cache – objects never collected while in cache class ReportCache: def __init__(self): self._cache = {} def store(self, key, value): self._cache[key] = value # Strong reference – keeps value alive def get(self, key): return self._cache.get(key) cache = ReportCache() class Report: def __init__(self, report_id): self.report_id = report_id report = Report("Q1") cache.store("Q1", report) del report # Object NOT collected – cache still holds a strong reference print(cache.get("Q1")) # Still accessible print(sys.getrefcount(cache.get("Q1"))) # Count > 1
Using weakref.ref()
A weak reference does not prevent garbage collection. When the object is collected, the weak reference returns None:
123456789101112131415161718import weakref class Report: def __init__(self, report_id): self.report_id = report_id def __repr__(self): return f"Report({self.report_id})" report = Report("Q2") weak = weakref.ref(report) # Creating a weak reference print(weak()) # Report(Q2) – object still alive print(weak() is report) # True del report # Last strong reference removed – object collected print(weak()) # None – object has been garbage collected
weakref.WeakValueDictionary — Automatic Cache Cleanup
WeakValueDictionary stores values as weak references. Entries are removed automatically when their values are garbage collected:
1234567891011121314151617181920212223import weakref class DataSet: def __init__(self, dataset_id): self.dataset_id = dataset_id def __repr__(self): return f"DataSet({self.dataset_id})" # Cache that doesn't prevent garbage collection of its values cache = weakref.WeakValueDictionary() dataset_a = DataSet("sales_2024") dataset_b = DataSet("costs_2024") cache["sales"] = dataset_a cache["costs"] = dataset_b print(dict(cache)) # Both entries present del dataset_a # Strong reference removed – entry auto-removed from cache print(dict(cache)) # Only 'costs' remains
weakref.WeakSet — Tracking Objects Without Owning Them
WeakSet stores objects as weak references – useful for observer registries where observers should not be kept alive by the registry itself:
1234567891011121314151617181920212223import weakref class EventListener: def __init__(self, name): self.name = name def on_event(self, event): print(f"{self.name} received: {event}") # Registry that doesn't prevent listeners from being collected listener_registry = weakref.WeakSet() listener_a = EventListener("dashboard") listener_b = EventListener("logger") listener_registry.add(listener_a) listener_registry.add(listener_b) print(f"Active listeners: {len(listener_registry)}") # 2 del listener_a # Removed from registry automatically print(f"Active listeners: {len(listener_registry)}") # 1
When to Use Weak References
Use weak references when:
- Building a cache that should release values when memory is needed;
- Implementing an observer or event system where listeners shouldn't be kept alive by the dispatcher;
- Tracking objects without claiming ownership of their lifetime.
Do not use them for objects that must stay alive for the duration of the program.
Grazie per i tuoi commenti!
Chieda ad AI
Chieda ad AI
Chieda pure quello che desidera o provi una delle domande suggerite per iniziare la nostra conversazione