Mixing functools.cached_property
and __getattr__
works well, except... when Exception raises:
from functools import cached_property
class A:
def __init__(self):
self.exists = 1
class B:
def __init__(self, a):
self.a = a
self.b = 1
def __getattr__(self, name):
return getattr(self.a, name)
@cached_property
def cached_func(self):
return self.not_exists
def func(self):
return self.not_exists
a = A()
b = B(a)
b.cached_func # 'A' object has no attribute 'cached_func'
b.func() # -> 'A' object has no attribute 'not_exists'
The Exception raised when using cached_property
is not explicit at all -- if not wrong. Is there a way to work around this?
OK, I found a way by adding a new decorator that will catch AttributeError before its propagation.
I created a specific Exception to better handle it during runtime.
from functools import cached_property, wraps
class NestedAttributeError(RuntimeError):
"""Specific exception for describing nested __getattr__ error"""
def intercept_AttributeError(func):
@wraps(func)
def wrapped(*args, **kwargs):
try:
return func(*args, **kwargs)
except AttributeError as exc:
raise NestedAttributeError(exc)
return wrapped
class A:
def __init__(self):
self.exists = 1
def __repr__(self):
return "AObj"
class B:
def __init__(self, a):
self.a = a
self.b = 1
def __repr__(self):
return "BObj"
def __getattr__(self, name):
#return getattr(self.a, name)
try:
attr = getattr(self.a, name)
except AttributeError as exc:
raise NestedAttributeError(exc)
return attr
@cached_property
@intercept_AttributeError
def cached_func(self):
a = self.not_exists
return a + 1
def func(self):
return self.not_exists
b = B(A())
b.cached_func # -> NestedAttributeError: 'A' object has no attribute 'not_exists'
b.func() # -> NestedAttributeError: 'A' object has no attribute 'not_exists'
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.