0

我正在处理一个我有一个 python 类 Foo 的场景。Foo,除其他事项外,还进行了许多大计算,除非需要,否则我不会这样做。那么,当我为其中一个大型计算定义 getter 方法时,如何确保与计算对应的方法(此处为 bigcalculation())已经运行?

class Foo:
    def __init__(self):
        #initialize some stuff
    def bigcalculation(self):
         #perform calculation
         self.big_calc_result=[big list of numbers];

    def get_big_calc_result(self):
        if hasattr(self,'big_calc_result')==False:
            self.bigcalculations();
        return sef.big_calc_result;

如果它运行一次,我不希望它再次运行。而且我不希望调用者必须跟踪它是否运行过一次。

现在,我使用上面的 hasattr() 函数来完成它,但我认为这是一种非常丑陋的方式。有没有更优雅的pythonic方式来做到这一点?

我能想到的另一种方法是在我的init () 函数中将我将在类中使用的所有变量定义为空列表。然后检查 big_calc_result 是否为空列表以确定 self.bigcalculation() 是否已经运行。这是更好的方法吗?

相关问题:Python 让我在类中动态定义变量。但这是不好的编程习惯吗?

编辑:回想起来,我还发现使用异常也可以是另一种处理这种情况的方法。这可能是一种更 Pythonic 的做事方式。

def get_big_calc_result(self):
    try:
        return self.big_calc_result;
    except AttributeError:
        self.bigcalculations();
        return self.big_calc_result;

这个问题的答案很有用: Checking for member exist in Python

4

1 回答 1

2

您可以记住结果并将其存储为属性:

class Foo(object):
    def __init__(self):
        self._big_calc_result = None

    @property
    def big_calc_result(self):
        if self._big_calc_result is not None:
            return self._big_calc_result
        else:
            self._big_calc_result = self.big_calc_run()
            return self._big_calc_result 

    def big_calc_run(self):
        time.sleep(10)  # Takes a long time ...

现在,您只需初始化类并获得结果:

f = Foo()
x = f.big_calc_result
y = f.bic_calc_result  # Look mom, this happened really quick

当然,如果属性不太直观,则不必使用属性,您可以在此处更改内容以适应您尝试提供的 API。真正的关键在于将结果缓存在带有下划线前缀的变量中,也就是说“这是一个实现细节——如果你把它弄乱了,你应该在未来的某个时候让你的代码中断”。

于 2014-06-25T03:41:24.640 回答