У меня проблема с Python-декоратором.
class decorator(object):
def __init__(self, function):
self.function = function
def __call__(self, *args, **kwargs):
print('sth to log: %s : %s' % (self.function.__name__, args))
return self.function(*args, **kwargs)
@decorator
def sum_test(a, b):
print('sum: %s' % (a+b))
@decorator
class Class_test(object):
def __init__(self):
pass
def sum_func(self, a, b):
print('class sum: %s' % (a+b))
return a+b
if __name__ == '__main__':
sum_test(3, 4)
func = Class_test()
var1 = func.sum_func(1, 4)
print(var1)
Выход:
sth to log: sum_test : (3, 4)
sum: 7
sth to log: Class_test : ()
class sum: 5
5
Декоратор работает так, как я хочу для функции sum_test
. Я могу sum_test
что функция sum_test
использовалась с переменными 3
и 4
.
У меня проблема с украшением классов. Я могу зарегистрировать, что объект класса Class_test
был создан, но у меня нет информации, что использовалась функция sum_func
.
Почему __call__()
в декораторе не запускается при запуске sum_func
для объекта класса и запускается при прямом использовании в функции sum_test
?
Украшение класса decorator
означает, что Class_test
теперь является объектом decorator
, так что Class_test.function
- это класс, для которого вы написали тело.
Помните, что синтаксис @decorator
является синтаксическим сахаром для
class Class_test(object):
def __init__(self):
pass
def sum_func(self, a, b):
print('class sum: %s' % (a+b))
return a+b
Class_test = decorator(Class_test)
(За исключением того, что символ Class_test
ни в коем случае не относится к вашему классу).
Таким образом, этот объект decorator
вызывается, когда вы вызываете Class_test
, и это именно то, что вы видите в своем журнале:
sth to log: Class_test : ()
func.sum_func
, с другой стороны, является обычным связанным методом. Он ничего не знает о decorator
.
Если вы собираетесь использовать его внутри классов, я бы предпочел декоратор в стиле замыкания (функция, которая возвращает функцию). Функция, которую она возвращает, обычно регистрируется методом class
машиной.
from functools import wraps
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
print('sth to log: %s : %s' % (func.__name__, args))
return func(*args, **kwargs)
return wrapper
class Class_test(object):
@decorator
def sum_func(self, a, b):
print('class sum: %s' % (a+b))
return a+b
Если вы все еще хотите использовать подход на основе классов, прочитайте Python Class Based Decorator с параметрами, которые могут украшать метод или функцию