我正在编写一个具有各种属性的类,我只想在必要时计算这些属性(惰性求值)。但是,更重要的是,我想确保如果它们的计算所依赖的任何属性发生更改,则不会返回“陈旧”值。除了实现某种计算图(有没有办法做到这一点?)之外,我想不出任何好的方法来做这件事,这涉及到很多 setter
方法和手工 -相关计算值的编码重置。
是否有更简单/更好或不易出错的方法来执行此操作? (我正在处理的实际应用程序比具有更大计算图的更复杂)
from math import pi
class Cylinder:
def __init__(self, radius, length, density):
self._radius = radius
self._length = length
self._density = density
self._volume = None
self._mass = None
@property
def volume(self):
if self._volume is None:
self._volume = self.length*pi*self.radius**2
print("Volume calculated")
return self._volume
@property
def mass(self):
if self._mass is None:
self._mass = self.volume*self.density
print("Mass calculated")
return self._mass
@property
def length(self):
return self._length
@length.setter
def length(self, value):
self._length = value
self._volume = None
self._mass = None
print("Volume and mass reset")
@property
def radius(self):
return self._radius
@radius.setter
def radius(self, value):
self._radius = value
self._volume = None
self._mass = None
print("Volume and mass reset")
@property
def density(self):
return self._density
@density.setter
def density(self, value):
self._density = value
self._mass = None
print("Mass reset")
(打印语句是临时的,仅供解释)
这行得通。在解释器中:
>>> c = Cylinder(0.25, 1.0, 450)
>>> c.radius
0.25
>>> c.length
1.0
>>> c.density
450
>>> c.volume
Volume calculated
0.19634954084936207
>>> c.mass
Mass calculated
88.35729338221293
>>> c.length = c.length*2 # This should change things!
Volume and mass reset
>>> c.mass
Volume calculated
Mass calculated
176.71458676442586
>>> c.volume
0.39269908169872414
>>>
我能找到的最接近的答案是 this one但我认为这是针对内存函数结果而不是属性值。
最佳答案
解决方法:
from math import pi
class Cylinder:
_independent = {"length", "radius", "density"}
_dependent = {"volume", "mass"}
def __init__(self, radius, length, density):
self._radius = radius
self._length = length
self._density = density
self._volume = None
self._mass = None
def __setattr__(self, name, value):
if name in self._independent:
name = f"_{name}"
for var in self._dependent:
super().__setattr__(f"_{var}", None)
if name in self._dependent:
print("Cannot set dependent variable!")
return
super().__setattr__(name, value)
@property
def volume(self):
if self._volume is None:
self._volume = self.length*pi*self.radius**2
print("Volume calculated")
return self._volume
@property
def mass(self):
if self._mass is None:
self._mass = self.volume*self.density
print("Mass calculated")
return self._mass
@property
def length(self):
return self._length
@property
def radius(self):
return self._radius
@property
def density(self):
return self._density
想法是使用__setattr__
来委托(delegate)所有集合操作。
关于python - 当依赖项更改时, 'intelligently' 在 Python 中重置记忆化属性值的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57439169/