8000 gh-127750: Improve singledispatchmethod caching · python/cpython@2e08bd9 · GitHub
[go: up one dir, main page]

Skip to content

Commit 2e08bd9

Browse files
committed
gh-127750: Improve singledispatchmethod caching
1 parent d8d12b3 commit 2e08bd9

File tree

2 files changed

+14
-8
lines changed

2 files changed

+14
-8
lines changed

Lib/functools.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,9 +1027,7 @@ def __init__(self, func):
10271027

10281028
self.dispatcher = singledispatch(func)
10291029
self.func = func
1030-
1031-
import weakref # see comment in singledispatch function
1032-
self._method_cache = weakref.WeakKeyDictionary()
1030+
self._method_cache = {}
10331031

10341032
def register(self, cls, method=None):
10351033
"""generic_method.register(cls, func) -> func
@@ -1041,13 +1039,12 @@ def register(self, cls, method=None):
10411039
def __get__(self, obj, cls=None):
10421040
if self._method_cache is not None:
10431041
try:
1044-
_method = self._method_cache[obj]
1045-
except TypeError:
1046-
self._method_cache = None
1042+
_obj_ref, _method = self._method_cache[id(obj)]
10471043
except KeyError:
10481044
pass
10491045
else:
1050-
return _method
1046+
if _obj_ref() is obj:
1047+
return _method
10511048

10521049
dispatch = self.dispatcher.dispatch
10531050
funcname = getattr(self.func, '__name__', 'singledispatchmethod method')
@@ -1062,7 +1059,14 @@ def _method(*args, **kwargs):
10621059
update_wrapper(_method, self.func)
10631060

10641061
if self._method_cache is not None:
1065-
self._method_cache[obj] = _method
1062+
obj_id = id(obj)
1063+
1064+
def _remove(_):
1065+
self._method_cache.pop(obj_id, None)
1066+
1067+
import weakref # see comment in singledispatch function
1068+
obj_ref = weakref.ref(obj, _remove)
1069+
self._method_cache[obj_id] = (obj_ref, _method)
10661070

10671071
return _method
10681072

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Improve caching of :class:`functools.singledispatchmethod` to fix issues
2+
where sometimes different object instances could collide with each other.

0 commit comments

Comments
 (0)
0