From 0b9eb7fdf100d62640dd2308eb904a2b2dbea9df Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 7 Sep 2024 11:53:17 -0500 Subject: [PATCH 1/2] Optimize cython cached_property implementation --- yarl/_helpers_c.pyx | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/yarl/_helpers_c.pyx b/yarl/_helpers_c.pyx index c428753d2..e6eec3754 100644 --- a/yarl/_helpers_c.pyx +++ b/yarl/_helpers_c.pyx @@ -1,5 +1,7 @@ # cython: language_level=3 +cdef _sentinel = object() + cdef class cached_property: """Use as a class method decorator. It operates almost exactly like the Python `@property` decorator, but it puts the result of the @@ -21,17 +23,14 @@ cdef class cached_property: return self.wrapped.__doc__ def __get__(self, inst, owner): - try: - try: - return inst._cache[self.name] - except KeyError: - val = self.wrapped(inst) - inst._cache[self.name] = val - return val - except AttributeError: - if inst is None: - return self - raise + if inst is None: + return self + cdef dict cache = inst._cache + val = cache.get(self.name, _sentinel) + if val is _sentinel: + val = self.wrapped(inst) + cache[self.name] = val + return val def __set__(self, inst, value): raise AttributeError("cached property is read-only") From e8eea5cabc37088cd7df74a61e326af0a216204a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 7 Sep 2024 14:37:38 -0500 Subject: [PATCH 2/2] changelog --- CHANGES/1122.misc.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 CHANGES/1122.misc.rst diff --git a/CHANGES/1122.misc.rst b/CHANGES/1122.misc.rst new file mode 100644 index 000000000..a911c35e9 --- /dev/null +++ b/CHANGES/1122.misc.rst @@ -0,0 +1 @@ +Improved performance of the Cython ``cached_property`` implementation -- by :user:`bdraco`.