3

NamedObject属性を持つクラスがあるとしますname。セッターを使用する必要がある場合は、最初に次のようにゲッターを定義する必要があります (推測しますか?)。

class NamedObject:
    def __init__(self, name):
        self.name = name

    @property
    def name(self):
        return self._name

今、セッター内で、ゲッターまたは実際の属性self._nameを使用する必要があるかどうか疑問に思っていましたか? self.name名前を設定するときは、オフにします。を使用する必要があります_nameが、セッターの内側にいるときはどうですか? 例えば:

@name.setter
def name(self, value):
    if self._name != str(value): # Or should I do 'if self.name != value' ?
        self.doStuff(self._name) # Or doStuff(self.name) ?
        self.doMoreStuff()
        self._name = str(value)

どちらを使用するかは実際に重要であり、なぜ一方を他方よりも使用するのですか?

4

4 に答える 4

3

セッターが内部インターフェースの一部である場合、外部インターフェースを使用する通常の理由はありません。必要に応じてシナリオを構築できると思いますが、デフォルトでは内部変数を使用するだけです。

于 2012-11-18T19:17:13.280 に答える
2

ゲッターに重要なロジック (遅延初期化など) がある場合は、常にゲッターを介してアクセスする必要があります。

class Something(object):
    UNINITIALIZED = object()
    LAZY_ATTRS = ('x','y','z')
    def __init__(self):
        for attr in self.LAZY_ATTRS:
            setattr(self, '_'+attr, self.UNINITIALIZED)
    def _get_x(self):
        if self._x is self.UNINITIALIZED:
            self._x = self.doExpensiveInitStuff('x')
        return self._x

ただし、getter が行うのがreturn self._xだけの場合は、内部変数に直接アクセスするだけです。

于 2012-11-18T19:49:50.977 に答える
1

内部変数にアクセスする代わりにゲッターを使用すると、設定ロジックに別の関数呼び出しが追加されます。Python では、関数呼び出しは高価です。これを書いている場合:

def _get_x(self):
    return self._x

def _set_x(self, value):
    self._x = value
x = property(fget=_get_x, fset=_set_x)

あなたは「Java が多すぎる」症候群に苦しんでいます。後で x の設定または取得に動作を追加する必要が生じた場合、クラス外の x へのすべてのアクセスを再コンパイルする必要があるため、Java 開発者はこの種のものを作成する必要があります。しかし、Python では、物事をシンプルに保ち、x をインスタンス変数として定義し、ある種の設定または取得動作を追加する必要が生じた場合にのみプロパティに変換する方がはるかに優れています。YAGNIYAGNIを参照してください。

于 2012-11-18T19:31:43.937 に答える
0

ポールはすでによく答えました。

完全を期すために、ゲッター/セッターを一貫して使用すると、クラスをオーバーライドしやすくなることを付け加えたいと思います。ここにはいくつかの意味があります。

特定のクラスが自分自身または他のユーザーによってオーバーライド/拡張​​される可能性が非常に高いと想定している場合は、早い段階でゲッター/セッターを使用すると、後でリファクタリングに費やす時間を短縮できるという点で有益です。それでも、シンプルに保つという観点に同意します。実行時のコストと読み取り/コーディングの労力のために、以下は控えめに使用してください。

検証が getter でも行われる場合は、インスタンス属性を直接 setter で使用するか、2 つの異なる gettername()および_name()(またはname_already_checked()) を提供して、両方をオーバーライドし、setter 内で検証せずに単純な getter を使用できるようにします。これは、高速で検証なしのタイプの getter と、顧客向けに提供されている通常の getter の両方を拡張できるようにするためです。

これは、 Paul が指摘した YAGNI 原則に違反しています。ただし、より多くのユーザー向けにコードをリリースする場合は、「オーバーエンジニアリング」が推奨されることがよくあります。ライブラリは、追加された柔軟性と先見の明から恩恵を受けます。

于 2012-11-19T12:08:54.423 に答える