getter和setter的Google Style Guide属性

时间:2014-02-28 22:46:17

标签: python properties decorator python-decorators google-style-guide

我对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以及两个下划线有什么好处,而不是直接使用两个下划线?

    < / LI>
  2. 为什么使用property()作为这种双重和三重下划线方法的方法,而不是做类似的事情:

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

1 个答案:

答案 0 :(得分:12)

在风格指南中,他们给出了一个理由:

  

如果未覆盖属性本身,则使用属性进行继承可能不明显。因此,必须确保间接调用访问器方法,以确保属性调用子类中重写的方法(使用模板方法DP)。

(其中模板方法DP Template Method Design Pattern(Alex Martelli的幻灯片,Google的非凡Pythonista)。

因此,他们希望为子类提供覆盖实现的机会,并为property三重下划线版本调用双下划线方法,以便您可以覆盖它们。在这种情况下,您必须拼出错误的名称:

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

显然,提出这个方案的人从来不知道你可以只是覆盖一个属性的吸气剂或者一个属性,请参阅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模式。