python - 当依赖项更改时, 'intelligently' 在 Python 中重置记忆化属性值的最佳方法

标签 python properties lazy-evaluation memoization getattribute

我正在编写一个具有各种属性的类,我只想在必要时计算这些属性(惰性求值)。但是,更重要的是,我想确保如果它们的计算所依赖的任何属性发生更改,则不会返回“陈旧”值。除了实现某种计算图(有没有办法做到这一点?)之外,我想不出任何好的方法来做这件事,这涉及到很多 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/

相关文章:

python - Paramiko 相当于管道控件和输入/输出管道

javascript - 在 Windows7 上安装 SRA-SiliconValley Jalangi 失败

python - 在Python中使用for循环读取文件

list - 删除语法糖 : List comprehension in Haskell

list - Haskell Tuple 在无限列表上的解构在将 Tuple 作为参数解构时与使用 let 解构时的行为不同

python - 如何在 Mac 上将 Python3 设置为默认的 python 版本?

java - OSGi 和持久性单元

ios - 我的自定义 @synchronize setter\getter 有什么问题吗?

php - 在不使用 $this-> 的情况下调用 protected 属性

linq - VS 2010和VS 2012中的不同LINQ答案