7

2 種類の MixIn を行うエレガントな方法を見つける必要があります。

初め:

class A(object):
    def method1(self):
        do_something()

-> -> -つまり、基本的に古い関数を「ラップ」しMixInClassます。これに対する適切な解決策が存在するに違いないと確信しています。method1do_other()A.method1()do_smth_else()

2番:

class B(object):
    def method1(self):
        do_something()
        do_more()

この場合、 と の間にMixInClass2自分自身を挿入できるようにしたいと考えています。つまり、-> ->です。おそらくこれには変更が必要であることを理解しています-それは大丈夫です、これを達成するための最も簡単な方法を探しているだけです.do_something()do_more()do_something()MixIn.method1do_more()class B

これらはかなり些細な問題であり、実際に解決しましたが、私の解決策は汚染されています。

の呼び出しを使用self._old_method1 = self.method1(); self.method1() = self._new_method1();して記述することにより、最初の 1 つ。_new_method1()_old_method1()

問題: 複数の MixIn がすべて _old_method1 に名前変更され、洗練されていません。

2 番目の MixIn は、ダミー メソッドを作成し、call_mixin(self): passそれを呼び出しと定義の間に挿入することで解決されましたself.call_mixin()。これもエレガントではなく、複数の MixIn で壊れます。

何か案は?


Boldewyn のおかげで、最初のソリューションに対するエレガントなソリューションを見つけました (元のコードを変更せずにオンザフライでデコレータを作成できることを忘れていました)。

class MixIn_for_1(object):
    def __init__(self):
        self.method1 = self.wrap1(self.method1)
        super(MixIn_for_1, self).__init__()

    def wrap1(self, old):
        def method1():
            print "do_other()"
            old()
            print "do_smth_else()"
        return method1

2番目のアイデアをまだ探しています(この場合のように、外部ではなく古いメソッドの内部に注入する必要があるため、このアイデアは適合しません)。


2 番目の解決策は以下のとおりです。「pass_func」を に置き換えlambda:0ます。

4

2 に答える 2

5

これは、デコレータを使用して非常に Pythonic な方法で処理できると思います。( PEP 318も)

于 2010-05-03T10:30:53.817 に答える
3

MixInClass1、MixinClass2 を実装する別の方法を次に示します。

デコレータは、多くの関数をラップする必要がある場合に便利です。関数を 1 つだけラップする必要があるためMixinClass1、モンキー パッチを適用する方が明確だと思います。

とに二重下線を使用する__old_method1__method1、 で便利な役割を果たしMixInClass1ます。Python の名前マングリング規則により、二重のアンダースコアを使用すると、これらの属性がローカライズされMixinClass1、不要な名前の衝突を引き起こすことなく、他の mix-in クラスにまったく同じ属性名を使用できるようになります。

class MixInClass1(object):
    def __init__(self):
        self.__old_method1,self.method1=self.method1,self.__method1
        super(MixInClass1, self).__init__()        
    def __method1(self):
        print "pre1()"
        self.__old_method1()
        print "post1()"

class MixInClass2(object):
    def __init__(self):
        super(MixInClass2, self).__init__()        
    def method1_hook(self):
        print('MixIn method1')

class Foo(MixInClass2,MixInClass1):
    def method1(self):
        print "do_something()"
        getattr(self,'method1_hook',lambda *args,**kw: None)()
        print "do_more()"

foo=Foo()
foo.method1()
于 2010-05-03T14:10:13.047 に答える