2011-08-18 4 views
9

を属性として動的にインスタンスメソッドを割り当てるに何か問題は、私は、引数としてインスタンス自体を必要とデコレータを使用してインスタンスメソッドを飾るために、次のコードを思い付いた:Pythonの:インスタンスが

from functools import wraps 

def logging_decorator(tricky_instance): 
    def wrapper(fn): 
     @wraps(fn) 
     def wrapped(*a, **kw): 
      if tricky_instance.log: 
       print("Calling %s.." % fn.__name__) 
      return fn(*a, **kw) 
     return wrapped 
    return wrapper  

class Tricky(object): 
    def __init__(self, log): 
     self.log = log 
     self.say_hi = logging_decorator(self)(self.say_hi) 

    def say_hi(self): 
     print("Hello, world!") 


i1 = Tricky(log=True) 
i2 = Tricky(log=False) 

i1.say_hi() 
i2.say_hi() 

これは素晴らしい動作しているようですしかし、私はこのトリックの意図しない副作用を見逃している可能性があることを恐れています。私は足で自分を撃っているのですか?これは安全ですか?

私は実際にこれをロギングに使用したくないことに注意してください。これは私が思い付くことができる最も短い意味のある例です。

+0

と思われます。私見では。 – Evpok

答えて

2

私は不必要にスマートにしようとしていたと思います。恥ずかしいほど簡単な解決策があるようです。

from functools import wraps 

def logging_decorator(fn): 
    @wraps(fn) 
    def wrapped(self, *a, **kw): 
     if self.log: 
      print("Calling %s.." % fn.__name__) 
     return fn(self, *a, **kw) 
    return wrapped 

class Tricky(object): 
    def __init__(self, log): 
     self.log = log 

    @logging_decorator 
    def say_hi(self): 
     print("Hello, world!") 

i1 = Tricky(log=True) 
i2 = Tricky(log=False) 

i1.say_hi() 
i2.say_hi() 
4

あなたがこれをやりたがっている理由はわかりません。あなたは新しいメソッドのタイプを割り当てたい場合は、動的にtypesを使用します。

import types 

class Tricky(object): 
    def __init__(self): 
     def method(self): 
      print('Hello') 
     self.method = types.MethodType(method, self) 

インスタンスで何かをしたい場合は、__init__方法でそれを行います。

def decorator(tricky_instance): 
    def wrapper(meth): 
     print(meth.im_self == tricky_instance) 
     return meth 
    return wrapper 

は個人的に、私は、これはたぶん-I-Shouldn't-使用-デコレータの地に方向転換されると思う:あなただけのデコレータ内部メソッドのインスタンスにアクセスしたい場合は、im_self属性を使用することができます。

+0

例外で示される(一時的な)ネットワークの問題について、インスタンスメソッドを自動的に呼び出そうと思います。一時的で永続的な例外は、実際のインスタンスに依存します(インスタンスは、整合性保証が格納場所に依存するAmazon S3オブジェクトを表します)。 – Nikratio

+0

あなたのコードが何をしているのかよく分かりません。あなたは詳しく説明できますか? – Nikratio

+1

私のコードは '__init__'に新しいインスタンスメソッドを作成します。私はあなたがデコレータを書こうとしていると思いますし、デコレータがデコレータを一般化するためにデコレータにメソッドのインスタンスにアクセスできるようにしたいのですか? – zeekay