Since Python 3.8, functools has a cached_property.
I've been using a similar lazyprop decorator based on Beazley's cookbook (code below), but when I replace by the builtin, I get problems. Here's one of them.
When I use the decorator within the class definition, using the @ operator, it doesn't complain.
But if I use it with setattr, I get:
TypeError: Cannot use cached_property instance without calling __set_name__ on it.
Beazley's simple version works fine though.
from functools import cached_property
class lazyprop:
"""Based on code from David Beazley's "Python Cookbook"."""
def __init__(self, func):
self.__doc__ = getattr(func, '__doc__')
self.func = func
def __get__(self, instance, cls):
if instance is None:
return self
else:
value = instance.__dict__[self.func.__name__] = self.func(instance)
return value
class D:
def __init__(self, greeting='Hello'):
self.greeting = greeting
def greet(self):
return self.greeting + " world!"
# Beazley's version works...
D.greet = lazyprop(greet)
assert D().greet == "Hello world!"
# ... but the builtin version will fail
D.greet = cached_property(greet)
# D().greet # this will fail