Python динамически добавляет декоратор в методы класса, украшая класс
скажем у меня есть класс:
class x:
def first_x_method(self):
print 'doing first_x_method stuff...'
def second_x_method(self):
print 'doing second_x_method stuff...'
и этот декоратор
class logger:
@staticmethod
def log(func):
def wrapped(*args, **kwargs):
try:
print "Entering: [%s] with parameters %s" % (func.__name__, args)
try:
return func(*args, **kwargs)
except Exception, e:
print 'Exception in %s : %s' % (func.__name__, e)
finally:
print "Exiting: [%s]" % func.__name__
return wrapped
как бы я написал другого декоратора otherdecorator
так что:
@otherdecorator(logger.log)
class x:
def first_x_method(self):
print 'doing x_method stuff...'
def first_x_method(self):
print 'doing x_method stuff...'
аналогично
class x:
@logger.log
def first_x_method(self):
print 'doing first_x_method stuff...'
@logger.log
def second_x_method(self):
print 'doing second_x_method stuff...'
или фактически заменить
@otherdecorator(logger.log)
class x:
С
@otherdecorator
class x:
где otherdecorator содержит все функциональные возможности (Я не человек python, поэтому будьте осторожны)
2 ответов
если нет определенной причины использовать класс в качестве декоратора, я думаю, что обычно проще использовать функции для определения декораторов.
вот один из способов создать декоратор класса trace
, который украшает все методы класса с log
оформитель:
import inspect
def log(func):
def wrapped(*args, **kwargs):
try:
print "Entering: [%s] with parameters %s" % (func.__name__, args)
try:
return func(*args, **kwargs)
except Exception, e:
print 'Exception in %s : %s' % (func.__name__, e)
finally:
print "Exiting: [%s]" % func.__name__
return wrapped
def trace(cls):
for name, m in inspect.getmembers(cls, inspect.ismethod):
setattr(cls,name,log(m))
return cls
@trace
class X(object):
def first_x_method(self):
print 'doing first_x_method stuff...'
def second_x_method(self):
print 'doing second_x_method stuff...'
x=X()
x.first_x_method()
x.second_x_method()
выходы:
Entering: [first_x_method] with parameters (<__main__.X object at 0xb77c80ac>,)
doing first_x_method stuff...
Exiting: [first_x_method]
Entering: [second_x_method] with parameters (<__main__.X object at 0xb77c80ac>,)
doing second_x_method stuff...
Exiting: [second_x_method]
вот версия trace
декоратор реализован как класс, который позволяет использовать другой вариант использования: передача функции для украшения всех функций-членов украшенного класса.
import inspect
def log(func):
def wrapped(*args, **kwargs):
try:
print "Entering: [%s] with parameters %s" % (func.__name__, args)
try:
return func(*args, **kwargs)
except Exception, e:
print 'Exception in %s : %s' % (func.__name__, e)
finally:
print "Exiting: [%s]" % func.__name__
return wrapped
class trace(object):
def __init__(self, f):
self.f = f
def __call__(self, cls):
for name, m in inspect.getmembers(cls, inspect.ismethod):
setattr(cls, name, self.f(m))
return cls
@trace(log)
class X(object):
def first_x_method(self):
print 'doing first_x_method stuff...'
def second_x_method(self):
print 'doing second_x_method stuff...'
x = X()
x.first_x_method()
x.second_x_method()