python применяет декоратор к каждому методу в классе без проверки

Немного изменив ответ из Применение декораторов Python к методам в классе, можно применить декоратор к каждому методу в классе. Есть ли способ сделать это без модуля проверки? Я пытался добиться этого, используя метаклассы и изменяя __getattribute__, но продолжаю получать бесконечную рекурсию. Из Как используется метод __getattribute__?, это можно исправить в обычных классах с помощью объекта .__ 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

Примечание: он не украшает staticmethod и classmethod

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