__metaclass__2 メソッドの置き換え

問題

実行に時間のかかる処理longlongtime_processを持つクラスAがある感じで。
このAを継承しているクラス、Aa,Abがある。

でも、longlongtime_processは時間がかかるので、テストの際には、それとは違うshorttime_processに変えたい。
以下のような階層関係のクラス。

# 階層構造

  A<have longlongtime_process>
  |__ Aa
  |__ Ab

# test ではAa,Abでshorttime_processを使いたい。
# longlongtime_processをshorttime_processに置き換えたい。

  A -> Aa -> AaProxy<have shortime_process>
  A -> Ab -> AbProxy<have shortime_process>

というクラスを作る必要がありそう。

このとき、shorttime_processでは、Aの持っている状態を利用したい。
でも、shorttime_processをひとつずつ追加したくない。(面倒)

こんな感じの実行結果にしたい

Aa:	longlongtime_process <x>message	y
Ab:	longlongtime_process <x>message	y	z
Aa:	Proxy longlongtime_process(short time)<x>message<x>	y
Ab:	Proxy longlongtime_process(short time)<x>message<x>	y	z

コード

__metaclass__を使ってできたのでコードを載せる。

# -*- coding:utf-8 -*-

class A(object):
    def __init__(self, x):
        self.x = x
        
    def longlongtime_process(self, message):
        #他との通信とか。時間のかかる処理。
        return "longlongtime_process "+self.x + message

    def g(self, result):
        raise Exception(result)

    def run(self, message):
        result = self.longlongtime_process(message)
        return self.g(result)

## longlongtime_processを書き換えたい。

class Aa(A):
    def __init__(self, x, y):
        super(Aa, self).__init__(x)
        self.y = y

    def g(self, result):
        text = "\t".join(["Aa:", result, self.y])
        print(text)

class Ab(A):
    def __init__(self, x, y, z):
        super(Ab, self).__init__(x)
        self.y = y
        self.z = z

    def g(self, result):
        text = "\t".join(["Ab:", result, self.y, self.z])
        print(text)

x, y, z = "<x>", "y", "z"
Aa(x, y).run("message")
Ab(x, y, z).run("message")

## idea
class AaProxy(Aa):
    def __init__(self, *args, **kw):
        super(AaProxy, self).__init__(*args, **kw)

    def longlongtime_process(self, message):
        return "Proxy shorttime_process..." + self.x + message + self.x

AaProxy(x, y).run("message")

class ProxyMeta(type):
    def __init__(cls, name, bases, attrs):
        def shorttime_process(self, message):
            return "Proxy shorttime_process..." + self.x + message + self.x
        setattr(cls, "longlongtime_process", shorttime_process)


class AbProxy(Ab):
    __metaclass__ = ProxyMeta

AbProxy(x, y, z).run("message")

クラスを継承したときに__init__を定義しないと、自動で親のクラスの__init__を呼んでくれる?

追記

多重継承で十分かも知れない

class A(object):
    def __init__(self, x):
        self.x = x

class AB(A):
    def __init__(self, x, y):
        super(AB, self).__init__(x)
        self.y = y

class UseXMixin(object):
    def use_x(self):
        print self.x

class ABC(AB, UseXMixin):
    pass

ABC(10, 20).use_x() # > 10

UseXMixinを継承しておけばメソッドが定義されるし、ABCのインスタンス変数を見るのでこれで大丈夫。

上の例に対応させると
class ShoftTimeProcessMixin(object):
    def longlongtime_process(self, message):
        return "Proxy shorttime_process..." + self.x + message + self.x

class AbProxy(ShoftTimeProcessMixin, Ab):
    pass

AbProxy(x, y, z).run("message")
# Ab:	Proxy shorttime_process...<x>message<x>	y	z

ただ、継承の順序を変えて(Ab,ShortTimeProcessMixin)だとうまく機能しない。
順序依存なので怖いかも。