对于问题的某些上下文 - 我使用延迟加载来推迟类中某些属性的完全初始化,直到需要它们的时间点(如果有的话),因为它们的计算成本很高。
我的问题是 - 在python中,如果在计算属性的值时发生错误,或者无法计算该值,是否可以提出异常或者客观上是个坏主意?
我知道这个问题:Best practices: throwing exceptions from properties - 并且在重复了这个问题之后,实际上重写了这个问题。
但是我真的在寻找关于python的明确答案。 例如,即使该值为None,getter总是返回一个值? 在其他语言中,例如c#,有关于如何设计属性的明确建议。
避免从属性getter中抛出异常。
属性getter应该是简单的操作,不应该有任何操作 前提条件。如果一个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
我一直是RTFM和很多关于属性的东西,但似乎看不到任何使用它或者发出警告的东西。这一切都完全可以接受,还是我从地狱创造了某种怪异的反模式?
我尝试这个的原因是因为我想到了一个像“懒惰”的描述符,它允许我快速标记属性。 e.g。
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))
然后
class A(object):
def __init__(self):
self.__x = None
@lazy
def x(self):
# where calculate_x might raise an exception
return calculate_x()
答案 0 :(得分:1)
我认为这个问题更适合软件工程堆栈。 但无论如何:我会尽量避免在吸气器中抛出异常,当你的脸突然爆炸时,这有点令人惊讶。 但是C#也有Lazy字段可以完全相同 - 所以从现实世界的经验我会说:尽量避免这个问题,除非有充分的理由做一些延迟加载,在这种情况下它可以没问题。
替代方法是提供一个Initialize方法,它会尝试或(我最喜欢)添加一个返回值的方法,但在第一次使用后在内部使用一个支持字段来缓存该值。
像这样:class bla(object):
expensive = None
def get_expensive():
if not expensive:
expensive =compute_expensive()
return expensive
答案 1 :(得分:0)
经过更多阅读并回到此处后,我将回答我自己的问题,并说不 - 根据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.
我意识到这在某种程度上解释了克里斯蒂安的答案 - 但我正在寻找关于这种模式的某种官方文件或指导。