《01》依存性:change&update(1)〈Python 3.0 版〉

Previous| |Next
Python à la carte記事一覧
《01》依存性:change&update(1)

《著》小粒ちゃん《監修》小泉ひよ子とタマゴ倶楽部
第3版♪2009/02/28
》作業中です《

事例: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

。《》□

Last updated♪09/03/16