16

次のクラス定義を検討してください

class of2010(object):
    def __init__(self):
        self._a = 1
        self._b = 2
        self._c = 3

    def set_a(self,value):
        print('setting a...')
        self._a = value
    def set_b(self,value):
        print('setting b...')
        self._b = value
    def set_c(self,value):
        print('setting c...')
        self._c = value
    a = property(fset=self.set_a)
    b = property(fset=self.set_b)
    c = property(fset=self.set_c)

set_[a|b|c]()同じことをすることに注意してください。定義する方法はありますか:

def set_magic(self,value):
    print('setting <???>...')
    self._??? = value

一度、次のようにa、b、cに使用します

a = property(fset=self.set_magic)
b = property(fset=self.set_magic)
c = property(fset=self.set_magic)
4

4 に答える 4

21
def attrsetter(attr):
  def set_any(self, value):
    setattr(self, attr, value)
  return set_any

a = property(fset=attrsetter('_a'))
b = property(fset=attrsetter('_b'))
c = property(fset=attrsetter('_c'))
于 2010-01-23T15:14:16.263 に答える
7

セッターはメッセージをログに記録してから、値を割り当てるだけです。実際、受け入れられた回答は値を割り当てるだけです。このパターンを使用しているのは、他の言語、おそらく名前が「J」で始まる言語での受け入れられた実践/従来の知識であるためですか?もしそうなら、この同じデザインへのPythonicアプローチがはるかに簡単であることを学んでください:

class Of2010(object):
    def __init__(self):
        self.a = 1
        self.b = 2
        self.c = 3

何もしないセッターや、値を割り当てるためだけの中間関数呼び出しはありません。"あなたが言うこと?「メンバー変数への公開?!!」ええ、実際にはそうです。

クライアントコードの観点からこれらのクラスを見てください。クラスを使用するには、クライアントはオブジェクトを作成し、次を使用してプロパティ「a」を割り当てます。

obj = Of2010()
obj.a = 42

驚くべきことに、これは私が上で投稿した5ライナークラスとまったく同じコードです。

J言語がより冗長なプロパティスタイルを推奨するのはなぜですか?要件が将来変更された場合にクラスインターフェイスを保持するため。ある時点で、オブジェクトの他の値がへの変更に合わせて変更する必要がある場合は、プロパティメカニズムを実装する必要があります。悲しいことに、J言語は属性アクセスメカニズムの性質をクライアントコードに公開するため、将来のある時点でプロパティを導入することは、そのクラスを利用するすべてのクライアントの再構築を必要とする煩わしいリファクタリングタスクです。およびその「a」属性。

Pythonでは、そうではありません。オブジェクトの「a」属性へのアクセスは、実行時に呼び出し元で決定されます。直接アクセスとプロパティアクセスはどちらも同じように見えるため、実際のメカニズムが異なっていても、Pythonクラスはこのインターフェイスを保持します。重要なのは、クライアントコードに関する限りそれが同一であるということです。

したがって、Javaでは、このプロパティの複雑さを、このクラスの開始時から(実際には、すべてのクラスのAccepted Practiceによって)、将来必要になる可能性があるときに導入します。Pythonを使用すると、機能する可能性のある最も単純なものを実装することから始めることができます。つまり、単純なメンバー変数に直接アクセスし、将来、余分なものが実際に必要で価値のある複雑なアプローチを残します。その日が実際に来ることはないかもしれないので、これはあなたのコードの最初の動作バージョンをドアから出すことにおいて大きな前進です。

于 2010-01-23T16:00:52.317 に答える
3

あなたが探しているかもしれません __setattr__(self, name, value)

こちらをご覧ください

于 2010-01-23T15:12:26.393 に答える
1
class...
 def __setattr__(self, name, value):
  print 'setting', name
  self.__dict__[name] = value

それでおしまい。

于 2010-01-23T15:20:23.723 に答える