71

私は実際にこれを行う必要はありませんが、関数ごとに明示的に宣言するのではなく、クラス内のすべての関数にデコレータを一般的にバインドする方法があるのではないかと思っていました。

デコレーターではなく、一種のアスペクトになると思いますが、少し奇妙に感じますが、タイミングや認証のようなものを考えていました。

4

9 に答える 9

41

これを行う、またはクラス定義に他の変更を加える最もクリーンな方法は、メタクラスを定義することです。

または、次を使用して、クラス定義の最後にデコレーターを適用するだけinspectです。

import inspect

class Something:
    def foo(self): 
        pass

for name, fn in inspect.getmembers(Something, inspect.isfunction):
    setattr(Something, name, decorator(fn))

もちろん実際には、デコレータをより選択的に適用したいと思うでしょう。1 つのメソッドを除くすべてのメソッドをデコレートしたい場合、従来の方法でデコレータ構文を使用する方が簡単で柔軟であることがすぐにわかります。

于 2010-08-12T12:59:54.517 に答える
36

クラス定義の変更を考えるときはいつでも、クラス デコレータまたはメタクラスを使用できます。たとえば、メタクラスを使用する

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 は装飾しません

于 2010-08-12T13:54:47.343 に答える
7

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

(これについてはダンカンに感謝します)

于 2019-07-05T08:48:44.410 に答える
-1

メソッドをオーバーライドできます__getattr__。実際にはデコレータをアタッチしているわけではありませんが、装飾されたメソッドを返すことができます。あなたはおそらく次のようなことをしたいと思うでしょう:

class Eggs(object):
    def __getattr__(self, attr):
        return decorate(getattr(self, `_` + attr))

そこには、保護したい醜い再帰が隠れていますが、それが始まりです。

于 2010-08-12T12:44:48.967 に答える