[issue42781] functools.cached_property docs should explain that it is non-overriding

Luciano Ramalho report at bugs.python.org
Tue Dec 29 17:36:32 EST 2020


Luciano Ramalho <luciano at ramalho.org> added the comment:

> FYI, the usual term is "data descriptor" instead of "overriding descriptor".

Yes, the Python docs are consistent in always using "data descriptor", but I've adopted "overriding descriptor" from Martelli's Python in a Nutshell--in Fluent Python I also put a note saying that "data descriptor" is used in the docs. I think "overriding descriptor" is more descriptive. In particular, I find "non-data descriptor" quite puzzling. But this issue is not about changing the jargon.

> 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.

I'd agree, if I wasn't personally bitten by the issue I reported. I was refactoring an existing class which had hand-made caches in a couple of methods decorated with @property. When I discovered @cached_property, I tried to simplify my code by using it, and it broke my code in one place, but not in the other. Leonardo Rochael had experience with cached_property and told me about the difference.

I suggest a warning noting the different behavior regarding existing instance attributes. The warning doesn't need to assume the user knows what is a descriptor, but it should in my opinion point to your excellent Descriptor HowTo Guide for more information.

> 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.

That's good too.

>> 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().

My idea would be to add a dummy __set__ method if the overriding option was True (default would be False). The method could raise an exception. But its presence would make @cached_property behave more like @property in the most common use case of @property: as an overriding descriptor emulating a read-only attribute.

>> 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.

You just did ;-). I filed this issue after spending hours trying to figure out what the problem was in my code on my second attempt at using @cached_property. I expected @cached_property would work as a drop-in replacement for @property when emulating a read-only attribute, and it did not.

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

Yes, the code snippet you suggested is a good way of saying "this produces a non-overriding descriptor". 

However we want to say it, I think it is important to contrast the behavior of @cached_property v. @property regarding the presence of attributes with the same name.

Cheers and a happy 2021 with two doses of vaccine for you and your loved ones, Raymond!

----------

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue42781>
_______________________________________


More information about the Python-bugs-list mailing list