在定义描述符类时,您可以简单地引发AttributeError
来表示该属性不可用。例如:
from typing import Any, TypeVar, MutableMapping
V = TypeVar("V")
class Desc:
def __init__(self, key: str) -> None:
self.key = key
def __get__(self, instance: Any, owner: type) -> V:
try:
return instance._dict[self.key]
except KeyError:
raise AttributeError()
class C:
foo = Desc("d")
def __init__(self, d: MutableMapping[str, V]) -> None:
self._dict = d
使用方式:
>>> d1 = dict(d=0, bar=0, baz=0)
>>> c = C(d1)
>>> c.foo
0
>>> d1.update(d=1)
>>> c.foo
1
>>> hasattr(C(dict()), "foo")
False
请注意,AttributeError
导致hasattr
函数“静默失败”。正如descriptor protocol所描述的那样。
但是,在某些情况下,您可能希望AttributeError
“冒泡”到顶部。例如:
class NewDesc:
def __get__(self, instance, owner):
do_complex_task(instance) # <-- AttributeError occurs here
return instance._on_the_fly_private_attr
我发现可以通过将有问题的代码包装在try-except块中来轻松解决,该代码会引发与AttributeError
不同的其他错误:
try:
do_complex_task(instance) # <-- AttributeError occurs here
except AttributeError as e:
raise MyError() from e
这是处理此问题的规范方法吗?这样做会让我有什么陷阱?