2009-04-15 10 views
4

親メソッド(私が装飾しているクラスの親の同じ名前のメソッド)を検査するメソッドのデコレータを作成しています。デコレータから装飾されたメソッドを所有するクラスへのアクセス

PEP 318の第4の例から)例:

def returns(rtype): 
    def check_returns(f): 
     def new_f(*args, **kwds): 
      result = f(*args, **kwds) 
      assert isinstance(result, rtype), \ 
        "return value %r does not match %s" % (result,rtype) 
      return result 
     new_f.func_name = f.func_name 
     # here I want to reach the class owning the decorated method f, 
     # it should give me the class A 
     return new_f 
    return check_returns 

class A(object): 
    @returns(int) 
    def compute(self, value): 
     return value * 3 

だから私は、私が欲しいここ#の代わりに入力するコードを探しています...

感謝。ここ

答えて

6

bobince said itとして、デコレータが呼び出された時点でクラスがまだ存在しないため、周囲のクラスにアクセスすることはできません。あなたは、クラスの完全な辞書と拠点へのアクセスが必要な場合は、metaclassを考慮する必要があります。

__metaclass__

この変数はname、bases、およびdictを任意の呼び出し可能な引数として取ることができます。クラスの作成時に、組み込みの型()の代わりに呼び出し可能関数が使用されます。

基本的に、私たちはクラスの建設にいくつかの魔法を行うにはメタクラスを告げるものにreturnsデコレータを変換:私は必要がある場合、私はこのコードをテストしていない

class CheckedReturnType(object): 
    def __init__(self, meth, rtype): 
     self.meth = meth 
     self.rtype = rtype 

def returns(rtype): 
    def _inner(f): 
     return CheckedReturnType(f, rtype) 
    return _inner 

class BaseInspector(type): 
    def __new__(mcs, name, bases, dct): 
     for obj_name, obj in dct.iteritems(): 
      if isinstance(obj, CheckedReturnType): 
       # do your wrapping & checking here, base classes are in bases 
       # reassign to dct 
     return type.__new__(mcs, name, bases, dct) 

class A(object): 
    __metaclass__ = BaseInspector 
    @returns(int) 
    def compute(self, value): 
     return value * 3 

マインド、コメントを残してくださいこれを更新してください。

非常にお薦めのDavid Mertzさんがarticles on metaclassesというものがありますが、これは興味深いものです。

+0

私の問題は私が言ったよりもはっきりとしていたので、私はあなたのコードを直接使用しませんでした。しかし、* name *が*型*構造体で一般的に使われるので、* dct *をトラバースするときに* name *を使うのはちょっと奇妙です。ありがとう、私はそれが私をたくさん助けたので、とにかくあなたの答えを受け入れることは大丈夫だと思う。 – Gra

+0

ああ、それは修正された間違いです。 –

6

私は装飾の時点では、何のクラスはメソッドfを所有していないので、あなたがすることはできません

F装飾されたメソッドを所有しているクラスに到達したいです。

class A(object): 
    @returns(int) 
    def compute(self, value): 
     return value * 3 

が言うように同じです:

class A(object): 
    pass 

@returns(int) 
def compute(self, value): 
    return value*3 

A.compute= compute 

明らかに機能が所有者クラスに割り当てられる前に、returns()デコレータが構築されています。

クラスにインラインまたは明示的にこのような関数を書くと、それはアンバウンドメソッドオブジェクトになります。デコレータで

>>> A.compute.im_class 
<class '__main__.A'> 

だからあなたが割り当てた後に実行される内部の「new_f」を、f.im_class読み取ることができますが、ではない:それはあなたが言って取得することができ、その所有者クラスへの参照を持っている今自体。

(あなたがしなくてもCPythonの実装の詳細を頼りにしていても、ちょっと醜いです。私はあなたが何をしようとしているのかはよく分かりませんが、 "所有者クラスを取得する"多くの場合、メタクラスを使用することができます)。

関連する問題