Skip to content

cached_property no longer works as a data descriptor in Python 3.12 #106292

Closed
@treyhunner

Description

@treyhunner

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

Linked PRs

Metadata

Metadata

Assignees

Labels

3.12only security fixes3.13bugs and security fixesstdlibPython modules in the Lib dirtype-bugAn unexpected behavior, bug, or error

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions