5

プロパティに関する Google Python スタイル ガイドの推奨事項の 1 つに興味があります。

その中で、彼らは次の例を挙げています。

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

これについて 2 つの質問があります。

  1. 2つのアンダースコアを直接使用するだけでなく、3つのアンダースコア「間接」___get_areaと2つのアンダースコアを使用する利点は何ですか?___set_area

  2. property()次のようなことをするのではなく、この二重および三重アンダースコア メソッドのセットでメソッドとして使用する理由:

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

1 に答える 1

13

スタイルガイドでは、理由を示しています。

プロパティ自体がオーバーライドされていない場合、プロパティの継承は明らかではありません。したがって、アクセサー メソッドが間接的に呼び出され、サブクラスでオーバーライドされたメソッドがプロパティによって呼び出されるようにする必要があります (テンプレート メソッド DP を使用)。

(ここで、Template Method DPTemplate Method Design Patternです(スライドは、Google の並外れた Pythonista である Alex Martelli によるものです)。

そのため、サブクラスに実装をオーバーライドする機会を与えproperty、トリプル アンダースコア バージョンにダブル アンダースコア メソッドを呼び出してこれらをオーバーライドできるようにしたいと考えています。その場合、マングルされた名前を綴る必要があります。

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

どうやら、このスキームを思いついた人々は、プロパティのゲッターまたはセッターだけをオーバーライドできることを知らなかったようです。セッターなしでゲッターをオーバーライドする Python を参照してください。

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

繰り返しになりますが、getter,setterおよびdeleterデコレータ属性は Python 2.6 でのみ追加されました。スタイル ガイドは、古い Python バージョン用に書かれている必要があります。

@propname.setter2.6 以降では、代わりにパターンに固執してください。

于 2014-02-28T22:58:51.863 に答える