Присоединение декоратора ко всем функциям в классе

Мне на самом деле не нужно это делать, но мне было просто интересно, есть ли способ привязать декоратор ко всем функциям в классе в общем, вместо того, чтобы явно указывать это для каждой функции. [12130 Я полагаю, что тогда это становится своего рода аспектом, а не декоратором, и это кажется немного странным, но он думал о чем-то вроде времени или аутентификации, и это было бы довольно аккуратно.

47
задан Kasramvd 18 April 2017 в 07:08
поделиться

3 ответа

Самый простой способ сделать это или внести другие изменения в определение класса - это определить метакласс.

Или просто примените свой декоратор в конце определения класса:

class Something:
   def foo(self): pass

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

Для Python 3 замените types.UnboundMethodType на types.FunctionType.

На практике, конечно, вы захотите применить свой декоратор более избирательно, и как только вы захотите украсить все, кроме одного метода, вы обнаружите, что проще и гибче просто использовать синтаксис декоратора в традиционном способ.

31
ответ дан 26 November 2019 в 19:50
поделиться

Каждый раз, когда вы думаете об изменении определения класса, вы можете использовать либо декоратор класса, либо метакласс. например с использованием метакласса

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

29
ответ дан 26 November 2019 в 19:50
поделиться

Вы можете переопределить метод __ getattr __ . На самом деле он не прикрепляет декоратор, но позволяет вам возвращать декорированный метод. Вы, вероятно, захотите сделать что-то вроде этого:

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

Там прячется какая-то уродливая рекурсия, от которой вы захотите защититься, но это только начало.

-1
ответ дан 26 November 2019 в 19:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: