按照设计,属性 getter 是否应该在 python 中抛出异常?

Fra*_*ser 5 python design-patterns properties exception getter-setter

对于问题的某些上下文 - 我使用延迟加载来推迟类中某些属性的完全初始化,直到需要它们时(如果有的话),因为它们的计算成本可能很高。

我的问题是 - 在 python 中,如果在计算属性值时发生错误,或者无法计算该值,那么引发异常是可以接受的还是客观上是一个坏主意?

我知道这个问题:最佳实践:从属性中抛出异常- 并且在回顾其中的要点后实际上重新措辞了这个问题。

然而,我真的在寻找有关 python 的明确答案。例如,getter 是否应该始终返回一个值,即使该值为 None?在其他语言中,例如 c#,对于如何设计属性有明确的建议。

避免从属性获取器抛出异常。

属性获取器应该是简单的操作,并且不应该有任何先决条件。如果 getter 可以抛出异常,那么它可能应该被重新设计为一个方法。请注意,此规则不适用于索引器,我们确实期望在验证参数时出现异常

http://msdn.microsoft.com/en-us/library/ms229006.aspx

在 python 中也是如此吗?这个属性真的应该是一个方法吗?我可以看到在强类型语言(例如 c#)中这可能是一个问题,但我不确定这里是否成立。在调试器中测试它按预期工作。

需要明确的是,我正在测试如下内容。

class A(object):
    def __init__(self):
        self.__x = None

    @property
    def x(self):
        if not self.__x:
            self.__x = calculate_x()
            if not some_test(self.__x):
                # Is this a bad idea?
                raise ValueError('Get x error {}'.format(self.__x))
        return self.__x

    @x.setter
    def x(self, value):
        if not some_test(value):
            raise ValueError('Set x error {}'.format(value))
        self.__x = value
Run Code Online (Sandbox Code Playgroud)

我一直是 RTFM 并了解很多有关属性的知识,但似乎看不到任何使用它或警告它的东西。这一切是完全可以接受的还是我创造了某种来自地狱的可怕的反模式?

我尝试这样做的原因是因为我想到了类似“惰性”描述符的东西,它允许我快速标记属性。例如

from functools import wraps

    class Descriptor(object):
        def __init__(self, func):
            self.func = func
        def __get__(self, obj, type=None):
            value = self.func(obj)
            setattr(obj, self.func.__name__, value)
            return value

    def lazy(func):
        return wraps(func)(Descriptor(func))
Run Code Online (Sandbox Code Playgroud)

然后

class A(object):
    def __init__(self):
        self.__x = None

    @lazy
    def x(self):
        # where calculate_x might raise an exception
        return calculate_x()
Run Code Online (Sandbox Code Playgroud)

Fra*_*ser 6

经过更多阅读并回到本文后,我将回答我自己的问题并说不 - 根据 PEP 8 风格指南,不推荐这样做。

https://www.python.org/dev/peps/pep-0008/

Note 3: Avoid using properties for computationally expensive operations;
the attribute notation makes the caller believe that access is (relatively) 
cheap.
Run Code Online (Sandbox Code Playgroud)

我意识到这在某种程度上解释了克里斯蒂安的答案 - 但我一直在寻找关于这种模式的某种官方文档或指导。