2013-10-24 34 views
2

很多時候我的類有幾個屬性,而其他對象的屬性依賴於這些屬性。什麼是定義和訪問這些的最佳方式? 一個簡單的例子應該解釋我在問什麼。鏈接到他人的對象屬性:如何保持一致性?

說我有一個類,定義了一個圈:

class Circle: 
    def __init__(self, r): 
     self.r = r 

現在這個圈子裏被實例化正是基於半徑,但我可能希望能夠訪問它的直徑,這些都是可能性我見:

A)創建一個新的屬性實例

class Circle: 
    def __init__(self, r): 
     self.r = r 
     self.d = 2*r 

B時的)定義返回的直徑的函數

class Circle: 
    def __init__(self, r): 
     self.r = r 
    def d(self): 
     d = 2*r 
     return d 

解決方案A不保證一致性,如果用戶更改r,d不會自動更新,並且可能很難追蹤到該錯誤。解決方案B要求用戶調用函數而不是訪問屬性。每次必須訪問屬性d時,都必須重新計算屬性d,並且通常可能會耗費大量時間。

是否有解決方案C確保一致性,並且不需要類用戶在每次訪問時重新計算屬性?

+0

我在問自己同樣的問題,但我對所給的迴應並不滿意。我認爲必須有一個更加優雅的方法來解決這個問題...... – MonkeyButter

回答

1

你可以在這裏使用Python屬性。

下面是內置的屬性函數在文檔中進行討論:

http://docs.python.org/2/library/functions.html#property

在你的情況,你可以按如下方式使用它:

def getdiameter(self): 
    return self.r * 2 

def setdiameter(self, d): 
    self.r = d/2 

d = property(getdiameter, setdiameter) 

您可能希望d是隻讀(這純粹是一個半徑的函數)。在這種情況下,您可以從屬性中省略setdiameter函數。

更新 如果d是非常昂貴的計算,那麼我會計算d時,它是第一次讀取和無效d時計算r。

def setr(self, r): 
    self.r = r 
    self.d = None 

def getd(self): 
    if not self.d is None: 
     return self.d 
    self.d = self.r * 2 # Our expensive calculation 
    return self.d 
+2

你應該使用'@ property'裝飾器。它提高了可讀性。 – ninMonkey

+0

這是我會這樣做的方式,但它不能解決OP每次都沒有進行重新計算的問題。你可以緩存它......但是每次'r'改變時你都必須使緩存無效。在這個例子中,我不確定有什麼意見... – Ben