This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author rhettinger
Recipients docs@python, ramalho, rhettinger
Date 2020-12-29.19:09:02
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1609268942.43.0.848071696893.issue42781@roundup.psfhosted.org>
In-reply-to
Content
FYI, the usual term is "data descriptor" instead of "overriding descriptor".

Normally the docs for things like property() and cached_property() don't mention the term descriptor at all.  From the user point of view, that is an implementation detail.  What is important is what it does and how to use it.

In the case of cached_property(), the docs do a pretty good job, "Transform a method of a class into a property whose value is computed once and then cached as a normal attribute for the life of the instance."

From a user point of view, that is exactly what happens.  The method is called exactly once.  The result is cached in an attribute and it behaves like a normal attribute for the remaining life (effectively, the descriptor is gone.

I would suggest a small amendment, and say "cached as a normal attribute with the same name".   The choice of attribute isn't arbitrary, it is exactly the same as the cached property.

> In the future, perhaps we can add an argument to @cached_property
> to optionally make it produce overriding descriptors.

That doesn't make any sense to me.  It would defeat the entire mechanism for cached_property().

> If a user replaces a @property with a @cached_property, her 
> code may or may not break depending on the existence of an 
> instance attribute with the same name as the decorated method. 

We've never had a report of an issue like this and I don't expect to see over.  In general, if someone is using property(), it is already a bit challenging to store and retrieve attributes that have the same name as the property.

I think it is sufficient to just state that cached_property() uses the attribute with the same name as the property.  That way, it won't be a "surprise" that attribute with the same name gets used :-)

One other possible addition is to note that the attribute is writeable:

class A:
    @cached_property
    def x(self):
        print('!')
        return 42

>>> a = A()
>>> vars(a)           # Initially, there is no instance variable
{}
>>> a.x               # Method is called
!
42
>>> vars(a)           # Data is stored in the instance variable
{'x': 42}
>>> a.x               # Method is not called again
42  
>>> a.x = 10          # Attribue is writeable
>>> vars(a)
{'x': 10}
>>> a.x
10
History
Date User Action Args
2020-12-29 19:09:02rhettingersetrecipients: + rhettinger, docs@python, ramalho
2020-12-29 19:09:02rhettingersetmessageid: <1609268942.43.0.848071696893.issue42781@roundup.psfhosted.org>
2020-12-29 19:09:02rhettingerlinkissue42781 messages
2020-12-29 19:09:02rhettingercreate