我有一个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
是否正确?
感谢。
答案 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)
基本上看起来不错。但由于x
和y
是可变的,因此如果_result
和x
将被修改,则需要使y
无效。
我也会在x
和y
之外设置属性,一旦设置为_result
无效。
有一件事,因为x
和y
是对lists
的引用(我想你的意思是在说arrays
时),这些列表可能会从范围MyClass
。如果发生这种情况,请遵循我建议使用属性,即使MyClass
和x
属性,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