Raymond Hettinger <raymond.hettin...@gmail.com> added the comment:

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

----------
nosy: +rhettinger

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue42781>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to