Декоратор классов и функций - PullRequest
0 голосов
/ 09 января 2019

У меня проблема с 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 использовалась с переменными 3 и 4.

У меня проблема с украшением классов. Я могу зарегистрировать, что объект класса Class_test был создан, но у меня нет информации, что использовалась функция sum_func.

Почему __call__() в декораторе не был запущен при запуске sum_func на объекте класса, и он был запущен при использовании непосредственно в функции sum_test?

1 Ответ

0 голосов
/ 09 января 2019

Обозначение класса с помощью 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 с параметрами, которые могут украшать метод или функцию

...