From 04fe64e5c261688149c28cb56db71f13d51dc8b5 Mon Sep 17 00:00:00 2001 From: mental Date: Tue, 10 Nov 2020 07:05:04 +0200 Subject: [PATCH] bpo-40988: Optimized singledispatchmethod access. --- Lib/functools.py | 13 +++++++++++++ .../2020-11-10-07-04-15.bpo-40988.5kBC-O.rst | 2 ++ 2 files changed, 15 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2020-11-10-07-04-15.bpo-40988.5kBC-O.rst diff --git a/Lib/functools.py b/Lib/functools.py index b1f1fe8d9a6f27..385858fc9b7e37 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -901,6 +901,7 @@ def __init__(self, func): self.dispatcher = singledispatch(func) self.func = func + self.attrname = None def register(self, cls, method=None): """generic_method.register(cls, func) -> func @@ -909,6 +910,9 @@ def register(self, cls, method=None): """ return self.dispatcher.register(cls, func=method) + def __set_name__(self, _, name): + self.attrname = name + def __get__(self, obj, cls=None): def _method(*args, **kwargs): method = self.dispatcher.dispatch(args[0].__class__) @@ -917,6 +921,15 @@ def _method(*args, **kwargs): _method.__isabstractmethod__ = self.__isabstractmethod__ _method.register = self.register update_wrapper(_method, self.func) + + if self.attrname is not None: + attrname = self.attrname + + try: + obj.__dict__[attrname] = _method + except AttributeError: + pass # not all objects have __dict__ (e.g. class defines slots) + return _method @property diff --git a/Misc/NEWS.d/next/Library/2020-11-10-07-04-15.bpo-40988.5kBC-O.rst b/Misc/NEWS.d/next/Library/2020-11-10-07-04-15.bpo-40988.5kBC-O.rst new file mode 100644 index 00000000000000..013bb509e7aca0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-11-10-07-04-15.bpo-40988.5kBC-O.rst @@ -0,0 +1,2 @@ +Applied a cached_propery type optimization suggested by federico to +singledispatchmethod yielding approximately a 3.5 speedup in access times.