2012-09-06 56 views
3

可能重複:
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) 

我認爲面積不計算在第一時間就被稱爲直到,但一旦它被稱爲是,緩存值直到某些內容發生變化或者每次調用時都會重新計算它?換句話說,如果我有一個屬性(不像這個)計算起來相對昂貴,並且會反覆使用,我應該讓它成爲一個屬性,還是將它作爲一個值存儲起來更有效率,以及當它真的需要更新時明確地明確它的含義?

+0

您不必選擇或者。如果尚未加載,您可以擁有一個緩存自己的屬性,然後可以按需定期回收。 –

回答

8

除非您明確地執行屬性,否則屬性不會被緩存,因此每次訪問屬性時都會運行代碼。嘗試:

@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 
+0

謝謝。所以這聽起來像是一個基本的屬性,就像這個例子對於計算便宜或者很少被引用的值來說很好。對於計算昂貴而且沒有改變而反覆引用的值,提供緩存的更復雜的東西似乎是明智的。 – TimothyAWiseman

+1

看起來像一個很好的分析。你甚至可以創建另一個封裝「屬性」的裝飾器來自動執行緩存過程。我在網上看到了一些例子,甚至有些庫使依賴鏈接過程更加明確,例如area> radius。 –

0

python中的裝飾器(如@property)在加載類時得到評估。有時候在類上產生的效果將包含額外的功能,但裝飾器本身只能運行一次。