Мне на самом деле не нужно это делать, но мне было просто интересно, есть ли способ привязать декоратор ко всем функциям в классе в общем, вместо того, чтобы явно указывать это для каждой функции. [12130 Я полагаю, что тогда это становится своего рода аспектом, а не декоратором, и это кажется немного странным, но он думал о чем-то вроде времени или аутентификации, и это было бы довольно аккуратно.
Самый простой способ сделать это или внести другие изменения в определение класса - это определить метакласс.
Или просто примените свой декоратор в конце определения класса:
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.
На практике, конечно, вы захотите применить свой декоратор более избирательно, и как только вы захотите украсить все, кроме одного метода, вы обнаружите, что проще и гибче просто использовать синтаксис декоратора в традиционном способ.
Каждый раз, когда вы думаете об изменении определения класса, вы можете использовать либо декоратор класса, либо метакласс. например с использованием метакласса
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
Вы можете переопределить метод __ getattr __
. На самом деле он не прикрепляет декоратор, но позволяет вам возвращать декорированный метод. Вы, вероятно, захотите сделать что-то вроде этого:
class Eggs(object):
def __getattr__(self, attr):
return decorate(getattr(self, `_` + attr))
Там прячется какая-то уродливая рекурсия, от которой вы захотите защититься, но это только начало.