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