2012-03-19 11 views
1

学習のために、私はクラスによって定義されたデコレータをチェーンしようとしています。私はthis question about decoratorsを読んでいます。これには、関数を使って連鎖することに関する多くの良い情報があります。また、documentationにリンクしていますが、もっと簡単な例を見つけようとしています。クラスとして定義されているチェーン化デコレータ?

基本的に、私はクラスを使用して同様の動作を模倣しようとしています。ここで私の最初のデコレータ定義は完璧に動作します。

class square_result(object): 
    def __init__(self, f): 
     pass 

def __call__(self, x, y): 
     return (x+y)**2 

@square_result 
def add_two_numbers(x, y): 
    return x + y 

print(add_two_numbers(2,5)) #Outputs 49, as expected 

その後、私はこのコードスニペットを作成するための別のデコレータを追加します。

class square_result(object): 
    def __init__(self, f): 
     pass 

    def __call__(self, x, y): 
     return (x+y)**2 

class append_abc(object): 
    def __init__(self, f): 
     pass 

    def __call__(self, *args): 
     return str(*args) + "abc" 

@append_abc 
@square_result 
def add_two_numbers(x, y): 
    return x + y 

print(add_two_numbers(2,5)) 
#Ideally, this should print "49abc" but prints "(2,5)abc" instead 

これを行うための適切な方法は何ですか?私がしたいことは、装飾する関数(この場合はsquare_result)の出力を受け取り、それに​​を追加するクラスの形でデコレータを作成することだと思います。

私は私のコードにデコレータを追加するとき、add_two_numbers()関数がコンパイルされ、その関数オブジェクトは、元add_two_numbers()に代入される関数のようなオブジェクトを作成するために何かをしsquare_resultクラスに渡されることを知っています。しかし、私はどのようにこれをチェーンするか分からない。

+0

あなたが投稿したバージョンはエラーです。 'str(* args)'から '*'を取り出し、あなたが言ったことをします。 – agf

+0

その行を '' return str(args)+ "abc" ''に変更しますか?それはうまくいかず、私にとっても同じ結果が得られます。 –

答えて

2

これは何をしたいん:あなたはデコレータの結果で、その出力を使用する場合は

class square_result(object): 
    def __init__(self, f): 
     pass 

    def __call__(self, x, y): 
     return (x+y)**2 

class append_abc(object): 
    def __init__(self, f): 
     self.f = f 

    def __call__(self, *args): 
     return str(self.f(*args)) + "abc" 

@append_abc 
@square_result 
def add_two_numbers(x, y): 
    return x + y 

print(add_two_numbers(2,5)) 

あなたが実際にはデコレータで内部関数を実行する必要があります。

最初のデコレータは編集しませんでしたが、実際にはデコレータとしては役に立ちません。その出力はどのような方法でも装飾されている関数には関連していないので、関数を置き換えるだけです。あなたがそのクラスに機能を交換したい場合は、それを行うための方法が

class square_result(object): 
    def __call__(self, x, y): 
     return (x+y)**2 

# this has no effect at all after the reassignment  
def add_two_numbers(x, y): 
    return x + y 

add_two_numbers = square_result() 

PEP8だろう、あなたのクラス名(SquareResult)のためのキャメルケースを示唆しています。

+0

優れています。私はちょうどそれを発見し、自分の質問に追加しましたが、私はそれを受け入れてあなたにポイントを与えるようにそれを元に戻しました。私は遅延が切れるとすぐにこれを受け入れます。 –

+0

私のファーストクラスのヒントもありがとう。私の更新されたコードは '' square_result''デコレータを作る正しい方法ですか? –

+1

@pythonscriptはい、回答は両方の誤りで意味があるので、私はそれを元に戻しました。 – agf

1

square_resultは結果をadd_two_numbersに "飾り付け"ませんが、それを上書きします(加算と二乗を行う)。代わりに、append_abcと同じ方法で装飾された関数を処理し、それを格納し、装飾された関数を独自の実装で使用する必要があります。したがって:

class square_result(object): 
    def __init__(self, f): 
     self.function = f 

    def __call__(self, *args): 
     return self.function(*args)**2 

class append_abc(object): 
    def __init__(self, f): 
     self.function = f 

    def __call__(self, *args): 
     return str(self.function(*args)) + "abc" 

@append_abc 
@square_result 
def add_two_numbers(x, y): 
    return x + y 

print(add_two_numbers(2,5)) 
関連する問題