python прилага декоратор към всеки метод в клас без проверка

Леко модифициране на отговора от Прилагане на декоратори на Python към методи в клас е възможно да се приложи декоратор към всеки метод в клас. Има ли някакъв начин да направите това без модула за проверка? Опитвам се да постигна това с помощта на метакласове и модифициране на __getattribute__, но продължавам да получавам безкрайна рекурсия. От Как се използва методът __getattribute__?, това може да бъде коригирано в нормални класове с помощта на object.__getattribute__ (себе си, име). Има ли нещо еквивалентно за метакласове?


person weeb    schedule 09.08.2012    source източник


Отговори (1)


Дефинирайте мета клас и след това просто приложете декоратор в края на дефиницията на класа.

class Classname:
   def foo(self): pass

for name, fn in inspect.getmembers(Classname):
    if isinstance(fn, types.UnboundMethodType):
        setattr(Classname, name, decorator(fn))

За Python 3 просто заменете types.UnboundMethodType с types.FunctionType.

но ако наистина не искате да използвате inspect, можете да го направите по този начин

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
         func(*args, **kwargs)
         print "after",func.func_name
      return wrapper

class MyKlass(object):
   __metaclass__ = DecoMeta

   def func1(self): 
      pass

MyKlass().func1()

Изход:

преди func1
след func1

Забележка: няма да украси статичен метод и метод на клас

person NIlesh Sharma    schedule 09.08.2012
comment
сигурен ли си, че няма да украси статичния метод? защото след като зададох този въпрос, открих __new__ и написах нещо много подобно, където статичният метод работи. - person weeb; 10.08.2012