11

私はさまざまな種類のオブジェクト(さまざまな関数名、さまざまな署名)をいくつか持っており、さまざまな関数からそれらにアクセスするための共通の方法を持つようにモンキーパッチを適用しています。簡単に言うと、パッチを適用したいオブジェクトを受け取るディスパッチャがあり、オブジェクトタイプに応じて異なるパッチャを呼び出します。パッチャーは、オブジェクトにメソッドを追加します。

def patcher_of_some_type(object):

    def target(self, value):
        # do something and call self methods

    object.target = types.MethodType(target, object)

    # many more of these

プログラムがより複雑になるにつれて、オブジェクト(またはオブジェクトクラス)のラッパーを作成することをお勧めします。一部のパッチャーは、共通のコードを共有するか、相互に関連しています。しかし、私はオブジェクトの作成もクラスの作成も制御しません。オブジェクトのみを取得します。そして、それができたとしても、すべてではなく、特定のオブジェクトをラップ(またはパッチ)したいだけです。

1つの解決策は、既存のオブジェクトに基本クラスを追加することかもしれませんが、これがどれほど保守可能で安全かはわかりません。別の解決策はありますか?

4

3 に答える 3

13

追加の基本クラスに互換性がある限り、オブジェクトの型を動的に変更することはかなり安全です(互換性がない場合は例外が発生します)。基本クラスを追加する最も簡単な方法は、3引数のtypeコンストラクターを使用することです。

cls = object.__class__
object.__class__ = cls.__class__(cls.__name__ + "WithExtraBase", (cls, ExtraBase), {})
于 2012-06-15T12:23:18.810 に答える
8

別の回答へのコメントに基づいて、これは基本クラスにパッチを適用する別の方法です。

class Patched(instance.__class__, ExtraBase):
    pass

instance.__class__ = Patched
于 2014-09-13T22:34:35.283 に答える
2

クラスを別のクラスベースに追加するには、次のようにします。

def pacher_of_some_type(object):

    #this class holds all the stuff you want to add to the object
    class Patch():
        def target(self, value):
            #do something

    #add it to the class' base classes
    object.__class__.__bases__ += (Patch, )

ただし、実際にクラス自体を変更すると、このクラスのすべてのオブジェクトに影響します。これは、希望どおりではないようです...インスタンスにパッチを適用するだけの場合は、元のクラスをサブクラス化して、インスタンスクラスを変更できます。動的に:

class PatchedClass(object.__class__):
    def target(self, value):
        #do whatever

object.__class__ = PatchedClass

安全性と管理性の観点から、基本クラスを動的に追加することは、一部の関数を動的に追加するのと同じくらい保守可能であり、新しい基本クラスが追加されるため、元のクラスの一部の内部関数を誤って上書きする可能性が低いため、より安全です。タプルの最後まで。つまり、名前解決のために最後に使用されます。実際にメソッドを上書きする場合は、それらを基本クラスのタプルの先頭に追加します(もちろん、これはサブクラスのアプローチには適用されません)。インスタンスのクラスを動的に変更することが安全かどうかを私に尋ねないでください。ただし、簡単な例では、問題はないようです。

class A():
    def p(self): print 1

class B():
    def p(self): print 2

a = A()
a.p()    #prints 1
a.__class__ = B
a.p()    #prints 2
于 2012-06-15T11:24:01.797 に答える