如何有效地使用Python属性?

gui*_*res 7 python properties

假设我有一个Foo存储一些统计数据的类,我想使用Python属性封装对这些数据的访问.这是特别有用的,例如,当我只存储变量的方差并希望能够访问其标准偏差时:在这种情况下,我可以定义属性Foo.std并使其返回方差的平方根.

这种方法的问题是,如果我需要Foo.std多次访问,我将每次计算平方根; 此外,由于属性的符号与属性的符号完全相同,因此我的类的用户可能不会意识到每次访问属性时都在进行计算.

此示例中的一个替代方案是每次更新方差时计算标准偏差,并将其设置为属性.但是,如果我不需要在每次更新时访问它,那将是低效的.

我的问题是:当您需要执行昂贵的计算时,有效使用Python属性的最佳方法是什么?我应该在第一次调用后缓存结果并在更新时删除缓存吗?或者我不应该使用属性并使用方法Foo.get_std()代替?

Wil*_*sem 7

通常你可以通过缓存来做到这一点.例如,您可以写:

class Foo:

    def __int__(self, also, other, arguments):
        # ...
        self._std = None

    @property
    def std(self):
        if self._std is None:
            # ... calculate standard deviation
            self._std = ...
        return self._std

    def alter_state(self, some, arguments):
        # update state
        self._std = None
Run Code Online (Sandbox Code Playgroud)

所以这里我们有一个std属性,但也有一个属性_std.如果尚未计算标准偏差,或者您更改了对象状态以使标准偏差可能已更改,我们将设置_stdNone.现在,如果我们进入.std,我们首先检查是否_stdNone.如果是这种情况,我们计算标准偏差并将其存储_std并返回.这样 - 如果对象没有改变 - 我们以后可以简单地检索它.

如果我们改变对象使得标准偏差可能已经改变,我们会_std回过头None来强制重新评估,以防我们.std再次访问.

如果我们在Foo重新计算标准差之前两次改变对象的状态,我们只会重新计算一次.所以,你可以经常更换Foo的对象,用(接近)参与(除设置没有额外的费用self._stdNone).因此,如果您拥有庞大的数据集并且进行了大量更新,那么您只需在实际需要时再努力计算标准偏差.

此外,这也可能是在(非常)便宜的情况下更新统计测量的机会.比如说,您有一个经常批量更新的对象列表.如果使用常量递增所有元素,则平均值也将随该常量递增.因此,改变状态以便一些指标也可以轻易改变的功能可能会更新指标,而不是更新指标None.

请注意,无论.std是属性还是函数都无关紧要.用户不必知道必须经常计算的频率.该std()功能将保证一旦计算,第二次检索将非常快.