Description
Bug report
In Python 3.11 and below, when cached_property
was inherited from, the __get__
method would always check for the attribute in the cache.
In Python 3.12.0b3 (since #101890 it seems) the __get__
method no longer checks the cache.
This isn't an issue for typical use, but it might be an issue for subclasses.
For example here's a version of cached_property
that inherits from the functools
version but also allows for a setter
(just as @property
does).
Since this child class adds a __set__
method, the __get__
method in functools.cached_property
will be called before the __dict__
attribute is accessed.
"""Demonstration of cached_property difference in Python 3.12.0b3.""" import functools class settable_cached_property(functools.cached_property): def __init__(self, func): super().__init__(func) self._setter = self._deleter = None def setter(self, setter): self._setter = setter return self def __set__(self, obj, value): if self._setter: self._setter(obj, value) obj.__dict__.pop(self.attrname, None) else: obj.__dict__[self.attrname] = value class Thing: @settable_cached_property def x(self): return self.y thing = Thing() thing.y = 4 print(f"{thing.x = } (should be 4)") thing.y = 5 print(f"{thing.x = } (should still be 4)")
This new behavior may be intended, but I wanted to make a note of it because it does break a previous (undocumented I believe?) assumption that cached_property
could be inherited from and turned into a data descriptor.
Your environment
Python 3.12.0b3 on Ubuntu Linux