《01》依存性:change&update(1)〈Python 3.0 版〉
《Previous| |Next》
Python à la carte《記事一覧》
《01》依存性:change&update(1)
関連記事
事例:change&update
モデルの値が変化(change)したことを、それに依存するオブジェクト群に通知することで、それに呼応して更新(update)が必要かどうかの判断を委ねます。
def ex(): m1 = ValueHolder("A") m1.compute(lambda e: print("... m1 =",repr(e))) m2 = ValueHolder("B") m2.compute(lambda e: print("... m2 =",repr(e))) m12 = BlockValue(lambda a,b: a+b, [m1,m2]) m12.compute(lambda e: print("... m12 =",repr(e))) m12.update() m1.value("C") m2.value("D")
モデル m1/m2 には、それぞれに文字列 "A"/"B" を初期値として設定します。モデル m1/m2/m12 は、自分の値が変化すると、メソッド compute で指定された処理 lambda を実行します。モデル m12 の値は、2つの文字列を連結した a+b もので、モデル m1,m2 の値に依存して変化します。
>>> ex()
... m12 = 'AB'
... m1 = 'C'
... m12 = 'CB'
... m2 = 'D'
... m12 = 'CD'
モデル m1 は、自分の値が 'A' から 'C' に変化すると、更新した値を出力するとともに、それに依存して変化するオブジェクト群に通知します。すると、モデル m12 は、モデル m1 の値が変化した通知を受けて、自分の値を 'AB' から 'CB' へと更新します。同様に、モデル m2 の値を 'D' に更新すると、モデル m12 は、自分の値を 'CB' から 'CD' へと更新します。
ValueModel
class ValueModel(object): def __init__(self): self.dependents = [] def value(self, value): self._value = value self.changed() def changed(self): for e in self.dependents: e.update() def update(self): pass def compute(self, closure): return BlockValue(closure, [self])
モデルに共通する特性を規定します。インスタンス属性 .dependents は、モデルの変化に呼応するオブジェクト群を保持します。
・メソッド value では、引数 value= に指定した値に更新するとともに、その値が変化したことを通知 changed します。
・メソッド changed では、モデルの変化に呼応する各オブジェクト e に対して、その値を更新 update するように依頼します。
・メソッド update では、何も規定していません。具体的な処理は、子孫クラスで規定されます。
・メソッド compute では、新たな BlockValue を生成することで、値が更新されたときの具体的な処理 closure を指定するとともに、そのとき自分 self が保持する値に依存して変化することを規定します。
ValueHolder
class ValueHolder(ValueModel): def __init__(self, value=None): super(self.__class__,self).__init__() self._value = value
ValueHolder は、自分の状態(保持する値)が変化したとき、それに呼応するオブジェクト群に通知します。すると、そのオブジェクトは、その変化(changed)に合わせて何を更新(update)すべきかを、自分で判断できるようになります。
・メソッド __init__ では、引数 value= に指定した値を、インスタンス属性 ._value に保持します。引数を省略すると、値 None が設定されます。インスタンス属性 .dependents の値が変化したときに、それに依存するオブジェクト群が呼応します。
BlockValue
class BlockValue(ValueModel): def __init__(self, closure, args): super(self.__class__,self).__init__() self.closure = closure self.args = args for e in args: e.dependents.append(self) def update(self): value = self.closure(*[e._value for e in self.args]) self.value(value)
インスタンス属性 .closure は、値が更新されたときの具体的な処理を規定します。インスタンス属性 .args は、自分の変化に呼応するオブジェクト群を保持します。そして、各オブジェクト e が依存する対象として、自分 self を追加登録しておきます。
・メソッド update では、値が更新されたときの処理 .closure を起動するときに、各オブジェクト群の値 ._value を参照します。この処理で得られた値 value を使って、自分の値を更新 .value するとともに、自分の変化に呼応するオブジェクト群に通知します。
Tips
。《》□