Acuisition

Acquisitionのtest.pyを読んでみました。

Acquisitionは、オブジェクトの属性を、その環境から取得するためのメカニズム。継承に似てるけど、継承の階層をトラバースするんじゃなくて、包含関係をトラバースする。

下の例のように、ExtensionClass.Baseをmix-inすると、サブクラスでacquisitionの機能が使えるようになる。

   >>> import ExtensionClass, Acquisition

    >>> class C(ExtensionClass.Base):
    ...   color='red'

    >>> class A(Acquisition.Implicit):
    ...   def report(self):
    ...     print self.color

    >>> a = A()
    >>> c = C()
    >>> c.a = a

    >>> c.a.report()
    red

    >>> d = C()
    >>> d.color = 'green'
    >>> d.a = a

    >>> d.a.report()
    green

    >>> a.report() # raises an attribute error
    Traceback (most recent call last):
    ...
    AttributeError: color

クラスAは、Acquisition.Implicitからacquisitionの機能を継承している。オブジェクトaは、cやdを介してアクセスしてるときはcolor属性を持っているけど、それ自体にはcolor属性を持っていない。aは、その環境からcolor属性を取得している。

Acquisition wrapper

acquisitionをサポートするオブジェクトがExtensionClassのインスタンスを介してアクセスされると、Acquisition wrapperと呼ばれる特殊なオブジェクトが返される。例えば上の例では c.a は、c と a に対する参照を含むラッパ−を返す。このラッパーは、aで属性が見つからなければ、cの属性を検索する。

acquisitionラッパーには、ラップされたオブジェクトにアクセスするための、'aq_parent', 'aq_self', 'aq_base'という属性がある。

例えば、上の例では次の式と

       >>> c.a.aq_parent is c
       1

そして、この式は

       >>> c.a.aq_self is a
       1


両方ともtrueに評価される。しかし、この式は

       >>> c.a is a
       0

falseになる。c.aは、cとaのラッパーであって、a自体ではない。

aq_baseは、aq_selfと同じようなものであるが、ラッパーはネストしていることがあるので、aq_selfが返すオブジェクトは、ラッパーであることがある。aq_baseは、すべてのラッパーを取除いて、その下にあるオブジェクトを指している。

続きはまた今度。