From 45466f11f200914cde2a4b5533441b93015ea14e Mon Sep 17 00:00:00 2001 From: Nick Pope Date: Wed, 19 Apr 2023 21:07:59 +0100 Subject: [PATCH] Removed function call overhead when preparing proxy class for lazy(). We can avoid the function call and assignment overhead which could be significant when instantiating many lazy objects. It's still easy enough to read too. --- django/utils/functional.py | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/django/utils/functional.py b/django/utils/functional.py index ed344166de..b78706e073 100644 --- a/django/utils/functional.py +++ b/django/utils/functional.py @@ -163,16 +163,6 @@ def lazy(func, *resultclasses): def __mod__(self, other): return self.__cast() % other - def __promise__(method_name): - # Builds a wrapper around some method. - def __wrapper__(self, *args, **kw): - # Automatically triggers the evaluation of a lazy value and - # applies the given method of the result type. - res = func(*self._args, **self._kw) - return getattr(res, method_name)(*args, **kw) - - return __wrapper__ - # Add wrappers for all methods from resultclasses which haven't been # wrapped explicitly above. for resultclass in resultclasses: @@ -182,8 +172,16 @@ def lazy(func, *resultclasses): # the correct implementation when called. if hasattr(__proxy__, method_name): continue - meth = __promise__(method_name) - setattr(__proxy__, method_name, meth) + + # Builds a wrapper around some method. Pass method_name to + # avoid issues due to late binding. + def __wrapper__(self, *args, __method_name=method_name, **kw): + # Automatically triggers the evaluation of a lazy value and + # applies the given method of the result type. + result = func(*self._args, **self._kw) + return getattr(result, __method_name)(*args, **kw) + + setattr(__proxy__, method_name, __wrapper__) @wraps(func) def __wrapper__(*args, **kw):