2010-05-04 45 views
9

我最近發現Python的property built-in,它將類方法getter和setter僞裝成類的屬性。我現在正在試圖以我非常確定不合適的方式使用它。何時使用「property」內建函數:輔助函數和生成器

使用property關鍵字顯然是正確的做法,如果A類的屬性_x的允許值要限制;即它將取代可能用C++編寫的getX()setX()結構。

但是還有什麼地方可以讓函數成爲一個屬性?舉例來說,如果你有

class Vertex(object): 
    def __init__(self): 
     self.x = 0.0 
     self.y = 1.0 

class Polygon(object): 
    def __init__(self, list_of_vertices): 
     self.vertices = list_of_vertices 
    def get_vertex_positions(self): 
     return zip(*((v.x,v.y) for v in self.vertices)) 

是適當補充

vertex_positions = property(get_vertex_positions) 

是否可以使發電機看起來像屬性?想象一下,如果我們的代碼發生變化,意味着我們不再以相同的方式存儲Polygon.vertices。那麼將它添加到Polygon可以嗎?

@property 
    def vertices(self): 
     for v in self._new_v_thing: 
      yield v.calculate_equivalent_vertex() 

回答

14
  • 當你有一個正常的屬性,並獲取和/或設置它對類的用戶有意義時,直接公開該屬性。公衆成員在某些語言中被詛咒的一個重要原因是,如果以後需要做更復雜的事情,則需要更改API;在Python中,你可以定義一個屬性。

  • 如果您使用的東西應該抽象爲屬性訪問,請使用屬性。如果您想讓外部狀態(您的情節或網站或其他東西)意識到更改,或者如果您要包裝某個直接使用成員的圖書館,那麼屬性可能就是要走的路。

  • 如果某物不屬於屬性y,則不要將其設爲屬性。做一個方法沒有什麼壞處,它可能是有利的:它做的更明顯,如果你需要的話你可以傳遞一些綁定的方法,你可以添加關鍵字參數而不需要改變API。

    很難想象我會使用生成器函數作爲屬性的情況。具有完全相同行爲的普通屬性的唯一方法是需要相當多的複雜性,所以這種情況不會讓人聯想到屬性訪問。

  • 您指出,您可以使用property限制訪問某些內部屬性_x。這可能是真的,但請記住

    • 如果你要爲安全或重要的事做的事情一樣清理輸入,明確的是比隱更好。當你遇到這樣的事情時,你不想像代碼一樣工作,因爲那樣你會遇到代碼不行。

    • 有時候人們使用property來實現只讀屬性。通常擁有一個普通屬性並且意識到你不能阻止用戶做一些愚蠢和不受支持的事情通常會更好。

  • 挑剔的您可能會感興趣:

    • property不是關鍵字;這是一個可以重新綁定的正常名稱。這是 有趣,因爲property不是一個語法或任何東西:它是一個普通的類,你可以在純Python中實現。它使用與Python-descriptors中的方法一樣的機制。

    • 你描述了什麼property做「僞裝類方法getter和setters」,這是不正確的。 property所做的事情只是普通的功能,根本不需要在班上實際定義; property會爲您通過self。除非您查看它們,否則函數實際上並不會成爲方法,當Python創建方法對象時。在課堂定義中,他們只是功能。當你有一個正常的方法時,它被稱爲「實例方法」;在Python中,「類方法」指another special thing類似的屬性,用於改變查找屬性時發生的情況。

2

有一個在使用性能的一個明顯的侷限性:它不接受任何參數,它永遠不會做。

所以你必須確定你正在轉換成一個屬性的函數永遠不會被重構成一個函數,例如,額外的默認參數。