7

いくつかのアクションを参照クラスに委譲するボイラー プレート クラスがあります。次のようになります。

class MyClass():

    def __init__(self, someClass):            
        self.refClass = someClass

    def action1(self):
        self.refClass.action1()

    def action2(self):
        self.refClass.action2()

    def action3(self):
        self.refClass.action3()

これはrefClassです:

class RefClass():

    def __init__(self):
        self.myClass = MyClass(self)

    def action1(self):
        #Stuff to execute action1

    def action2(self):
        #Stuff to execute action2

    def action3(self):
        #Stuff to execute action3

Python Metaprogramming を使用して、これをよりエレガントで読みやすくしたいのですが、方法がわかりません。

setattrgetattrについて聞いたことがありますが、次のようなことができると思います

class MyClass():

    def __init__(self, someClass):            
        self.refClass = someClass

    for action in ['action1', 'action2', 'action3']:
        def _delegate(self):
            getattr(self.refClass, action)()

そして、私はどこかからこれを行う必要があることを知っています、私は推測します:

MyClass.setattr(action, delegate)

私はこの概念を完全に理解することはできません。コードを繰り返さないこと、および関数型プログラミングで for ループを使用してメソッドを生成することについての基本は理解していますが、このメソッドを他の場所から呼び出す方法がわかりません。ひーえーぷ!

4

2 に答える 2

8

Python には、含まれているクラスへの一般化された委譲のサポートが既に含まれています。の定義をMyClass次のように変更するだけです。

class MyClass:

    def __init__(self, someClass):            
        self.refClass = someClass  # Note: You call this someClass, but it's actually some object, not some class in your example

    def __getattr__(self, name):
        return getattr(self.refClass, name)

定義さ__getattr__れている場合、インスタンス自体で属性が見つからない場合はいつでも、アクセスされた属性の名前を持つインスタンスで呼び出されます。getattr次に、含まれているオブジェクトの属性を検索し、それを返すために呼び出して、含まれているオブジェクトにデリゲートします。これは、動的ルックアップを行うたびに少しコストがかかるため、回避したい場合は、属性が によって最初に要求されたときに属性を遅延キャッシュして__getattr__、その後のアクセスが直接になるようにすることができます。

def __getattr__(self, name):
     attr = getattr(self.refClass, name)
     setattr(self, name, attr)
     return attr
于 2015-09-28T17:44:50.980 に答える
2

個人的には、物事を委任するために、私は通常次のようなことをします:

def delegate(prop_name, meth_name):
    def proxy(self, *args, **kwargs):
        prop = getattr(self, prop_name)
        meth = getattr(prop, meth_name)
        return meth(*args, **kwargs)
    return proxy

class MyClass(object):
    def __init__(self, someClass):
        self.refClass = someClass

    action1 = delegate('refClass', 'action1')
    action2 = delegate('refClass', 'action2')

これにより、必要なすべてのデリゲート メソッドが作成されます :)

いくつかの説明については、ここでのデリゲート関数は、クラス メソッドとして機能する「プロキシ」関数を作成し (self引数を参照してください)、それに与えられたすべての引数を、argsおよびkwargs引数を使用して参照されるオブジェクトのメソッドに渡します ( *args およびを参照)。これらの引数の詳細については、**kwargs? )

リストを使ってこれを作成することもできますが、私にとってはより明示的であるため、最初のものを好みます:)

class MyClass(object):
    delegated_methods = ['action1', 'action2']

    def __init__(self, someClass):
        self.refClass = someClass

        for meth_name in self.delegated_methods:
            setattr(self, meth_name, delegate('refClass', meth_name))
于 2015-09-28T17:27:58.147 に答える