私は実際にこれを行う必要はありませんが、関数ごとに明示的に宣言するのではなく、クラス内のすべての関数にデコレータを一般的にバインドする方法があるのではないかと思っていました。
デコレーターではなく、一種のアスペクトになると思いますが、少し奇妙に感じますが、タイミングや認証のようなものを考えていました。
私は実際にこれを行う必要はありませんが、関数ごとに明示的に宣言するのではなく、クラス内のすべての関数にデコレータを一般的にバインドする方法があるのではないかと思っていました。
デコレーターではなく、一種のアスペクトになると思いますが、少し奇妙に感じますが、タイミングや認証のようなものを考えていました。
これを行う、またはクラス定義に他の変更を加える最もクリーンな方法は、メタクラスを定義することです。
または、次を使用して、クラス定義の最後にデコレーターを適用するだけinspectです。
import inspect
class Something:
def foo(self):
pass
for name, fn in inspect.getmembers(Something, inspect.isfunction):
setattr(Something, name, decorator(fn))
もちろん実際には、デコレータをより選択的に適用したいと思うでしょう。1 つのメソッドを除くすべてのメソッドをデコレートしたい場合、従来の方法でデコレータ構文を使用する方が簡単で柔軟であることがすぐにわかります。
クラス定義の変更を考えるときはいつでも、クラス デコレータまたはメタクラスを使用できます。たとえば、メタクラスを使用する
import types
class DecoMeta(type):
def __new__(cls, name, bases, attrs):
for attr_name, attr_value in attrs.iteritems():
if isinstance(attr_value, types.FunctionType):
attrs[attr_name] = cls.deco(attr_value)
return super(DecoMeta, cls).__new__(cls, name, bases, attrs)
@classmethod
def deco(cls, func):
def wrapper(*args, **kwargs):
print "before",func.func_name
result = func(*args, **kwargs)
print "after",func.func_name
return result
return wrapper
class MyKlass(object):
__metaclass__ = DecoMeta
def func1(self):
pass
MyKlass().func1()
出力:
before func1
after func1
注: staticmethod と classmethod は装飾しません
Python 3 の更新:
import types
class DecoMeta(type):
def __new__(cls, name, bases, attrs):
for attr_name, attr_value in attrs.items():
if isinstance(attr_value, types.FunctionType):
attrs[attr_name] = cls.deco(attr_value)
return super().__new__(cls, name, bases, attrs)
@classmethod
def deco(cls, func):
def wrapper(*args, **kwargs):
print("before",func.__name__)
result = func(*args, **kwargs)
print("after",func.__name__)
return result
return wrapper
(これについてはダンカンに感謝します)
メソッドをオーバーライドできます__getattr__。実際にはデコレータをアタッチしているわけではありませんが、装飾されたメソッドを返すことができます。あなたはおそらく次のようなことをしたいと思うでしょう:
class Eggs(object):
def __getattr__(self, attr):
return decorate(getattr(self, `_` + attr))
そこには、保護したい醜い再帰が隠れていますが、それが始まりです。