2017-02-02 2 views
1

ライブラリにあるクラスを更新したいと思いますが、そのクラスを制御できません(元のソースコードには触れません)。制約番号2:他のユーザーはすでにこの親クラスを継承しており、3番目のクラスから継承するように頼むと、少し煩わしいことになります。だから私は同時に両方の制約を扱わなければならない:親クラスを拡張する必要があるが、継承することはできない。スタティックデコレータを使用した動的装飾

"monkey-patching"に隣接していますが、1つの解決策が最初はもっと意味があるようでした。親クラスのいくつかのメソッドを自分でオーバーライドします。私はそれを行うことができる小さなデコレータを書いた。しかし、いくつかのエラーが発生しました。完全なコードを提供するのではなく、ここに例があります。 (とにかく、そのソースコードについて)ここでは、旧(親クラス)という名前の以下のクラスは、私は触れることができないライブラリであることを考えてみましょう:

単純なクラス、コンストラクタとメソッドをだ
class Old(object): 

    def __init__(self, value): 
     self.value = value 

    def at_disp(self, other): 
     print "Value is", self.value, other 
     return self.value 

パラメータを使って(もう少しテストするため)。これまで何も本当に難しいことはありませんでした。しかし、ここに私のデコレータがこのクラスのメソッドを拡張するために来る:

​​

驚いたことに、これは完全に動作します。 Oldインスタンスを作成し、at_dispメソッドを呼び出すと、新しいメソッドが呼び出されます(古いものを呼び出す)。隠された継承のようなもの。しかしここには本当の挑戦があります:

私たちは古いものを継承しようとします。それはユーザーがやったことです。それはクラッシュ...あなたは新しいオブジェクトを作成した場合

class New(Old): 
    def at_disp(self, other): 
     print "That's in New..." 
     return super(Old, self).at_disp(self, other) 

、及びそのat_disp方法を試してみてください。私の「パッチは」彼らが何かをするために必要とせず、あまりにもそれらに適用されるべきです。 super()はOldのat_dispを見つけることができません。奇妙です.NewはOldから直接継承するからです。私の推測は、新しい、置き換えられたメソッドはバインドされていないので、super()はそれを正しく見つけられません。 Old()を直接呼び出してsuper()を置き換えると、すべてが機能します。

誰かがこの問題を解決する方法を知っていますか?なぜそれが起こるのですか?

ありがとうございました!

答えて

1

2つの問題。

最初に、superへの呼び出しはsuper(New, self)でなく、super(Old, self)である必要があります。 superの第1引数は、一般に「現在の」クラス(すなわち、メソッドがsuperを呼び出すクラス)である。

第2に、at_dispメソッドへの呼び出しはat_disp(other)であり、at_disp(self, other)ではありません。 superの2つの引数を使用すると、インスタンスのように動作するバインドされたスーパーオブジェクトが取得されるため、メソッドを呼び出すとselfが自動的に渡されます。

したがって、コールはsuper(New, self).at_disp(other)である必要があります。その後、それは動作します。

+0

完璧に、ありがとう!私はそれを逃して恥ずかしいです:S。 –

関連する問題