2009-04-01 16 views
3

クラス構造内にデコレータを書く方法はありますか?たとえば、これはクラスなしで正常に動作します:デコレータとクラス

def wrap1(func): 
    def loc(*args,**kwargs): 
     print 1 
     return func(*args,**kwargs) 
    return loc 

def wrap2(func): 
    def loc(*args,**kwargs): 
     print 2 
     return func(*args,**kwargs) 
    return loc 


def wrap3(func): 
    def loc(*args,**kwargs): 
     print 3 
     return func(*args,**kwargs) 
    return loc 

def merger(func): 
    return wrap1(wrap2(wrap3(func))) 


@merger 
def merged(): 
    print "merged" 


@wrap1 
@wrap2 
@wrap3 
def individually_wrapped(): 
    print "individually wrapped" 

merged() 
individually_wrapped() 

出力は次のようになります。

1 
2 
3 
merged 
1 
2 
3 
individually wrapped 

私が欲しいものです。しかし、ここではmergedindividually_wrappedを静的メソッドまたはクラスメソッドにしたいとしましょう。これは、デコレータがクラス名前空間の外に置かれている限り、動作します。名前空間内にデコレータを配置する良い方法はありますか?私はむしろ動作しないすべての方法を列挙したくないですが、主な問題は、mergerがメソッドの場合、wrapXメソッドにアクセスできないということです。たぶん、これはやりたい愚かなことですが、同じクラスのすべてのデコレータと装飾されたメソッドで、このような何かを得た人がいますか?

答えて

5

"名前空間内にデコレータを配置する良い方法はありますか?"

これには理由はありません。モジュールファイルがあります。それらはクラスといくつかのデコレータのためのきれいな容器です。

クラスのメソッドとしてデコレータを使用する必要はありません。別のメソッドから呼び出すことができます。

+0

私はこれが進むべき道だと思います。クラス内でそれらを保つためには大きな理由がありません。 –

2

実際、クラス内にそれらをすべて入れても問題ありません。クラス本体の内部で、あなたは単にそれを命名することにより、これまでに定義された任意の変数に名前を付けることができた場合:Pythonはクラス本体を実行中の関数は、変数を「見る」ことができるので、結果3が得られ

 
class A(object): 
    a = 1 
    b = 2 
    c = a + b 

print A.c 

とbが宣言されている。したがって、以下も同じです:

 
class B(object): 
    @staticmethod 
    def wrapper(*args, **kw): 
     ... 

    @wrapper 
    def a(...): 
     ... 

今、あなたの合併機能はどうですか?問題は、の実行後にラッパー関数が長くに実行され、クラス本体が実行され、定義された変数がもはや囲みスコープにないことです。それでは、どうやってそれらを参照できますか?接頭辞としてクラスの名前を使用することによって!このように:

 
class C(object): 
    @staticmethod 
    def wrap1(*args, **kw): 
     ... 
    @staticmethod 
    def wrap2(*args, **kw): 
     ... 
    @staticmethod 
    def wrap3(*args, **kw): 
     ... 
    @staticmethod 
    def merger(*args, **kw): 
     C.wrap1(C.wrap2(C.wrap3(...))) 

    @merger 
    def plain(...): 
     ... 

だから、Pythonの持つ一般的なルールは次のとおりです。右のクラス本体のレベルで実行されるコード、その中に、これまでに定義されているすべての変数やメソッドについて話すことができ、この手段これらのクラス変数をラッパーとして使用できます。しかし、クラス関数、静的関数、またはメソッド(このラッパーは引数を取るのでクラスメソッドですが、 "self"はありません)でも、クラスの関数の "内部"に入ると、その内容「の取得」するクラスの名前。

+0

良い点。私は名前でクラスを参照する必要がある場合 –

+0

はい、そういう理由がないかもしれません。あなたが単に参照するのを簡単にしたいのであれば、それをするだけですクラス外のラッパーを使用すると、クラス定義の内側とその関数内の両方から「見る」ことができます。 –

関連する問題