Декоратор классов и функций

1

У меня проблема с 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?

  • 2
    Примечание: я рекомендую использовать замыкания внутри функций вместо полноценного класса .
  • 0
    Что вы хотите, чтобы декоратор делал при применении к классу? Это предназначено для украшения каждого метода класса?
Показать ещё 2 комментария
Теги:
class
decorator

1 ответ

0
Лучший ответ

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

  • 0
    Должен ли я иметь другой декоратор для класса? У меня есть проблема при прямом украшении функции в классе: return self.function (* args, ** kwargs) TypeError: sum_func () отсутствует 1 обязательный позиционный аргумент: 'b' Как указать декоратору возвращать функцию этому классу?
  • 0
    @Pablo Я добавил раздел к моему ответу, чтобы обратиться к этому.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню