2009-09-02 15 views
45

私はクラス内のメソッドをデコレートしようとしていますが、Pythonはエラーを投げています。私のクラスには、次のようになります。クラス内のメソッドを飾る方法は?

from pageutils import formatHeader 

myPage(object): 
    def __init__(self): 
     self.PageName = '' 

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

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

if __name__=="__main__": 
    page = myPage() 
    page.PageName = 'My Page' 
    page.createPage() 

#------- pageutils.py -------------------- 

def formatHeader(fn): 
    def wrapped(): 
     return '<div class="page_header">'+fn()+'</div>' 
    return wrapped 

Pythonは、次のエラー

 
self.createHeader() 
TypeError: wrapped() takes no arguments (1 given) 

私は暇つぶしのですがスローされますか?

答えて

29

Pythonは自動的にクラスインスタンスを参照として渡します。 (すべてのクラスメソッドに見られるself引数)。

あなたが行うことができます:あなたは装飾のない機能(お使いの場合はcreateHeader)に存在する自己パラメータを省略している

def formatHeader(fn): 
    def wrapped(self=None): 
     return '<div class="page_header">'+fn(self)+'</div>' 
    return wrapped 
+0

ああ...と「createHeader」で、あなたが戻ってきていますタプル。これを代わりに: 'return" Page Header "+ self.PageName' – exhuma

+0

技術的には、デコレータをクラスの外でも使いたい場合を除いて、' def wrapped(self) 'を行うこともできます。しかし、装飾された機能は、「自己」を優雅に扱う必要があります。 – exhuma

+0

だから 'fn'は' fn(self、...) 'と同じですか、あるいはself ifのどこを考える正しい方法は何ですか? –

48

def formatHeader(fn): 
    from functools import wraps 
    @wraps(fn) 
    def wrapper(self): 
     return '<div class="page_header">'+fn(self)+'</div>' 
    return wrapper 

あなたが飾るしたい機能の署名について不明な点がある場合は、次のように、あなたはそれではなく、一般的にすることができます。

def formatHeader(fn): 
    from functools import wraps 
    @wraps(fn) 
    def wrapper(*args, **kw): 
     return '<div class="page_header">'+fn(*args, **kw)+'</div>' 
    return wrapper 
+16

'def wrapper(* args、** kw)で+1:' from functools import wraps'のために ' –

+1

+1。これには、ラップされた関数からドキュメンテーション文字列が公開されるという利点があります。それを使わない理由はありません! – jorgeh

関連する問題