【问题标题】:When and how often are properties calculated in python? [duplicate]在 python 中计算属性的时间和频率是多少? [复制]
【发布时间】:2012-08-31 17:05:04
【问题描述】:

可能重复:
python: are property fields being cached automatically?

出于对 python 中属性效率的担忧,我想知道它们何时以及多久被调用一次。

举一个简单的例子,假设我是 namedtuple 的子类,我有类似的东西:

from collections import namedtuple
from math import pi

class Circle (namedtuple('Circle', 'x, y, r')):
    __slots__ = ()

    @property
    def area(self):
        return pi*self.r**2

unitCircle = Circle(0, 0, 1.0)
print 'The area of the unit circle is {0} units'.format(unitCircle.area)

我假设在第一次调用之前不会计算面积,但是一旦调用,该值是否会缓存到某些内容发生变化,还是每次调用时都会重新计算?

换一种说法,如果我有一个属性(与这个不同)计算起来相对昂贵并且会被重复使用,我应该让它成为一个属性,还是将它存储为一个值并显式存储更有效真的需要更新的时候计算一下?

【问题讨论】:

  • 您不必选择或。如果尚未加载,您可以拥有一个缓存自身的属性,然后可以根据需要定期重新缓存。

标签: python


【解决方案1】:

除非您明确执行,否则不会缓存属性,因此每次访问属性时都会运行代码。试试:

@property
def area(self):
    try:
        return self._area
    except AttributeError:
        area = pi*self.r**2
        self._area = area
        return area

如果您希望能够偶尔根据需要重新计算值,请执行以下操作:

@property
def area(self):
    try:
        return self._area
    except AttributeError:
        self.recalc_area()
        return self._area

def recalc_area(self):
    self._area = pi*self.r**2

或者,如果您想更自动地执行此操作:

@property
def area(self):
    try:
        return self._area
    except AttributeError:
        area = pi*self.radius**2
        self._area = area
        return area

@property
def radius(self):
    return self._radius

@radius.setter
def radius(self, radius):
    try:
        del self._area
    except AttributeError:
        pass
    self._radius = radius

【讨论】:

  • 谢谢。所以听起来像示例这样的基本属性对于计算成本低或很少引用的值很好。对于计算成本高且重复引用而不更改的值,提供缓存的更复杂的东西似乎是明智的。
  • 似乎是一个很好的分析。您甚至可以创建另一个封装 property 的装饰器,它可以自动执行缓存过程。我已经在网络上看到了一些例子,甚至还有一些库使依赖链接过程对于 area>radius 等内容更加明确。
【解决方案2】:

python 中的装饰器(如@property)在加载类时得到评估。有时对类的最终效果会包含额外的功能,但装饰器本身只运行一次。

【讨论】:

    猜你喜欢
    • 2012-10-08
    • 2021-12-04
    • 2021-09-21
    • 2014-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-24
    相关资源
    最近更新 更多