Pythonic方法将方法结果存储为属性

时间:2016-05-11 22:02:03

标签: python class oop

我有一个python类,其属性可以对大型数组执行操作。在第一次计算方法的结果之后存储方法结果的最佳方法是什么,而不是在每次访问属性时都重做操作?

例如:

class MyClass:
    def __init__(self, x, y):
        """Input variables are two large data arrays"""
        self.x = x
        self.y = y

    @property
    def calculate(self):
        """Some computationally expensive operation"""
        try:
            # the result has been calculated already
            return self._result
        except AttributeError:
            # if not, calculate it
            self._result = self.x * self.y
            return self._result

用法:

>>> foo = MyClass(2,3)
>>> a = foo.calculate
>>> print(a)
6

正如您所看到的,到目前为止我想出的只是存储结果的“隐藏”属性。有一个更好的方法吗?在这里使用@property是否正确?

感谢。

4 个答案:

答案 0 :(得分:3)

您需要记住用于计算缓存结果的x和y值。如果它们发生变化,则需要重新计算并刷新缓存。

class MyClass:
    def __init__(self, x, y):
        """Input variables are two large data arrays"""
        self.x = x
        self.y = y
        self._calculate = None
        self._x = None
        self._y = None

    @property
    def calculate(self):
        if not self._calculate or self._x != self.x or self._y != self.y:
            self._calculate = self.x * self.y
            self._x = self.x
            self._y = self.x

        return self._calculate


>>> a = MyClass(2,3)
>>> print(a.calculate)
6
>>> a.x = 553
>>> print(a.calculate)
1659

答案 1 :(得分:2)

您实施财产的方式很好。它有效,并且几乎没有开销。

作为思想实验,您可以利用非数据描述符的特定属性。非数据描述符类似于npm run start-prod-api(它是数据描述符)。非数据描述符是仅定义property方法的对象。当实例具有与非数据描述符同名的属性时,这将覆盖非数据描述符(想想猴子修补函数)。例如

__get__

答案 2 :(得分:1)

基本上看起来不错。但由于xy是可变的,因此如果_resultx将被修改,则需要使y无效。

我也会在xy之外设置属性,一旦设置为_result无效。

有一件事,因为xy是对lists的引用(我想你的意思是在说arrays时),这些列表可能会从范围MyClass。如果发生这种情况,请遵循我建议使用属性,即使MyClassx属性,y也无法检测到这些更改。我会接受这个限制,但记录得很好。

答案 3 :(得分:0)

您可以将对象初始化为None,然后检查它是否仍为None

class MyClass:
    def __init__(self, x, y):
        """Input variables are two large data arrays"""
        self.x = x
        self.y = y
        self._result = None

    @property
    def calculate(self):
        """Some computationally expensive operation"""
        if self._result is not None:
            return self._result
        # if not, calculate it
        self._result = self.x * self.y
        return self._result