我有多个使用单个变量的函数,这个变量的计算成本很高,所以我不想重复这个。我有两个简单的方法可以做到这一点,并且想知道你感觉更多" pythonic"或者更好的方法。
class A:
def __init__(self):
self.hasAttr = False
def compute_attr(self):
self.attr = 10
self.hasAttr = True #for func2 only
def func1(self):
try:
print self.attr == 10
except AttributeError:
self.compute_attr()
self.func1()
def func2(self):
if not self.hasAttr: self.compute_attr()
print self.attr == 10
a = A()
a.func1()
a.func2()
func1使用一个简单的尝试,除了捕获AttributeError并在这种情况下计算属性。 func2使用存储的布尔值来检查计算是否已经完成。
有没有理由认为一种方法比另一种方法更受欢迎?此外,在func2中定义执行检查的装饰器是否有任何意义?
感谢您的帮助。
答案 0 :(得分:2)
基本上你的问题是“should I use EAFP or should I use LBYL”。答案是:这取决于。 try / except块几乎可以自由设置,但是在使用时非常昂贵(当实际出现异常时),而测试具有常量(并且对于这种测试而言相当便宜)成本,所以如果你经常没有属性集你可能更喜欢LBYL解决方案,而如果你确信它已经在大部分时间设置了,那么EAFP可能是更好的选择。
另请注意,还有更简单(且更可靠)的方法来测试您的属性是否已经计算 - 通过在初始化程序中使用sentinel值设置它 - None
是一个明显的候选者,除非它恰好是有效值 - 或使用hasattr(obj, attrname)
。您还可以使用属性来封装访问,即:
class EAFB(object):
@property
def attr(self):
try:
return self._attr
except AttributeError:
self._attr = costly_computation()
return self._attr
def func(self):
print "attr is %s" % self.attr
class LBYL(object):
@property
def attr(self):
if not hasattr(self, "_attr"):
self._attr = costly_computation()
return self._attr
def func(self):
print "attr is %s" % self.attr