5

我很好奇Google Python style guide concerning properties中的推薦之一。谷歌風格指南屬性獲取和設置器

在這裏面,他們給了下面的例子:

class Square(object): 
    """A square with two properties: a writable area and a read-only perimeter. 

    To use: 
    >>> sq = Square(3) 
    >>> sq.area 
    9 
    >>> sq.perimeter 
    12 
    >>> sq.area = 16 
    >>> sq.side 
    4 
    >>> sq.perimeter 
    16 
    """ 

    def __init__(self, side): 
     self.side = side 

    def __get_area(self): 
     """Calculates the 'area' property.""" 
     return self.side ** 2 

    def ___get_area(self): 
     """Indirect accessor for 'area' property.""" 
     return self.__get_area() 

    def __set_area(self, area): 
     """Sets the 'area' property.""" 
     self.side = math.sqrt(area) 

    def ___set_area(self, area): 
     """Indirect setter for 'area' property.""" 
     self.__set_area(area) 

    area = property(___get_area, ___set_area, 
        doc="""Gets or sets the area of the square.""") 

    @property 
    def perimeter(self): 
     return self.side * 4 

我對這個兩個問題:

  1. 什麼是用三個下劃線「間接」 ___get_area___set_area作爲受益以及兩個下劃線,直接使用兩個下劃線的直接?

  2. 爲什麼使用property()的方法與這套雙重和三重底線方法,而不是做這樣的事情:

    @property 
    def area(self): 
        return self.side ** 2 
    
    @area.setter 
    def area(self, value): 
        self.side = math.sqrt(value) 
    

回答

12

在風格指南他們給的理由:

如果屬性本身沒有被覆蓋,則屬性的繼承可能不明顯。因此,必須確保間接調用訪問器方法,以確保屬性調用子類中的方法重寫(使用Template Method DP)。

(其中模板方法DP是由亞歷克斯·馬爾泰利,Pythonista非凡在谷歌)的Template Method Design Pattern(幻燈片。

所以他們想給子類覆蓋實現的機會,並給予property的。三下劃線版本調用雙下劃線方法,所以您可以覆蓋這些,你不得不在這種情況下拼出重整名稱:

class WonkySquare(Square): 
    def _Square__get_area(self): 
     return self.square ** 2 + 0.5 

顯然是來瓦特的人第i該方案從來不知道,你可以覆蓋只是一個getter或屬性的setter方法,請參見Python overriding getter without setter

class ProperlySubclassedSquare(Square): 
    @Square.area.getter 
    def area(self): 
     return self.square ** 2 + (0.5 - 0.5) 

話又說回來,gettersetterdeleter裝飾屬性只在Python 2.6增加。風格指南必須是爲較舊的Python版本編寫的。

對於2.6及更高版本,請改爲使用@propname.setter模式。

+0

謝謝!那麼,如果我正確地理解了你,你會推薦我在第二個問題(即@property和@ area.setter)中說的話,然後在ProperlySubclassedSquare中使用你的方法進行子類化? – mindvirus

+0

@mdkess:絕對;風格指南幾乎肯定是爲較舊的Python版本編寫的。 –