0

以前のスレッドのフォローアップとして、私の質問は、この式をどのように取ることができるかということです。これfn(self,*args, **kwargsをooのように呼び出すとself.fn(...)、失敗した行がコメント化された私の全体的なプログラムになります。

def formatHeader(fn):
    def wrapped(*args, **kwargs):
        print "here is args prior to extraction - {0}".format(args)
        if len(args) > 1:
            self,args = args  # remove self from args
        else:
            self, args= args[0], ()
        print("Here are the arguments after extraction: {0} {1}".format(self, args))
        #return '<div class="page_header">' + self.fn(*args, **kwargs)+'</div>'
        return '<div class="page_header">' + fn(self,*args, **kwargs)+'</div>'
    return wrapped    

class MyPage(object):
    def __init__(self):
        self.PageName = ''

    def createPage(self):
        pageHeader = self.createHeader()
        return pageHeader

    def addem(self, a, b):
        return a + b

    @formatHeader   #<----- decorator
    def createHeader(self):
        return "Page Header " + self.PageName


obj = MyPage()

print obj.createHeader()
4

2 に答える 2

3

まず、selfそのスコープには存在しません。 self慣例により、クラスのインスタンス メソッド内の現在のインスタンスを参照するラベルです。第二に、デコレーターは、ラップしている関数のインスタンスを認識することを意図していません (少なくともデフォルトでは)。メソッドはインスタンスにバインドされ、デコレーターは、ブラック ボックス呼び出し可能として渡されたバインドされたメソッドで動作します。デコレーター内からインスタンス メンバーにアクセスしたい場合 (これは実際には oo を壊してしまうため、そうすべきではありません)、インスタンスをデコレーターに渡す必要があります。これは、デコレーターをさらにクロージャーで囲むことを意味します。またはイントロスペクションを使用して、デコレーター コード内から所有インスタンスを動的に検出します。

于 2012-08-01T15:44:05.743 に答える
1

問題は、ラッパーが適用されているインスタンスの別のメソッドにアクセスしたいのですが、デコレータが実行されるクラス定義時とは対照的に、実行時まで渡されないことです)。基本的に、インスタンス固有のメソッド デコレーターが必要です。これは、 PythonDecoratorLibraryのインスタンスレシピを使用するクラス メソッド デコレータで説明されているように、デコレータを記述子にすることで実現できます。

これをサンプル コードに適用すると、次のようになります (表面的な変更がいくつかあります)。

from functools import wraps

def formatHeader(fn):

    class Descriptor(object):
        def __init__(self, fn):
            self.fn = fn

        def __get__(self, instance, klass):
            if instance is None:  # Class method was requested
                return self.make_unbound(klass) #  will raise TypeError
            return self.make_bound(instance)

        def make_unbound(self, klass):
            @wraps(self.fn)
            def wrapped(*args, **kwargs):
                '''This documentation will vanish :)'''
                raise TypeError(
                    'unbound method {}() must be called with {} instance '
                    'as first argument (got nothing instead)'.format(
                        self.fn.__name__, klass.__name__)
                )
            return wrapped

        def make_bound(self, instance):
            @wraps(self.fn)
            def wrapped(*args, **kwargs):
                '''This documentation will disapear :)'''
                return ('<div class="page_header">' +
                        self.fn(instance, *args, **kwargs) + '</div>')

            # This instance does not need the descriptor anymore,
            # let it find the wrapped method directly next time:
            setattr(instance, self.fn.__name__, wrapped)
            return wrapped

    return Descriptor(fn)

class MyPage(object):
    def __init__(self):
        self.PageName = ''

    def createPage(self):
        pageHeader = self.createHeader()
        return pageHeader

    def addem(self, a, b):
        return a + b

    @formatHeader   #<----- decorator
    def createHeader(self):
        return "Page Header " + self.PageName


obj = MyPage()

print obj.createHeader()

ネストされた Descriptor クラス メソッドの引数は、(コード内にある)selfメソッドがラップされたクラスではなく、Descriptor クラスのインスタンスを参照することに注意してください。instance

于 2012-08-01T19:26:58.147 に答える