diff options
| author | Simon Charette <charette.s@gmail.com> | 2024-01-13 14:21:36 -0500 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2024-01-15 05:56:33 +0100 |
| commit | d074c7530b812a7b78c9a201c8a70f281ed3a36e (patch) | |
| tree | 518955c30ed741af8df3a9c6a9978670ea7b76be | |
| parent | 92d6cff6a2fee7a3f9244081b84fd82c50cc71aa (diff) | |
Refs #35102 -- Optimized Expression.identity used for equality and hashing.
inspect.signature() is quite slow and produces the same object for each
instance of the same class as they share their __init__ method which
makes it a prime candidate for caching.
Thanks Anthony Shaw for the report.
| -rw-r--r-- | django/db/models/expressions.py | 13 |
1 files changed, 9 insertions, 4 deletions
diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py index c20de5995a..9ee2d65c8a 100644 --- a/django/db/models/expressions.py +++ b/django/db/models/expressions.py @@ -14,7 +14,7 @@ from django.db.models import fields from django.db.models.constants import LOOKUP_SEP from django.db.models.query_utils import Q from django.utils.deconstruct import deconstructible -from django.utils.functional import cached_property +from django.utils.functional import cached_property, classproperty from django.utils.hashable import make_hashable @@ -485,13 +485,18 @@ class BaseExpression: class Expression(BaseExpression, Combinable): """An expression that can be combined with other expressions.""" + @classproperty + @functools.lru_cache(maxsize=128) + def _constructor_signature(cls): + return inspect.signature(cls.__init__) + @cached_property def identity(self): - constructor_signature = inspect.signature(self.__init__) args, kwargs = self._constructor_args - signature = constructor_signature.bind_partial(*args, **kwargs) + signature = self._constructor_signature.bind_partial(self, *args, **kwargs) signature.apply_defaults() - arguments = signature.arguments.items() + arguments = iter(signature.arguments.items()) + next(arguments) identity = [self.__class__] for arg, value in arguments: if isinstance(value, fields.Field): |
