Декорирование метода класса методом класса

Я украшал метод класса другим методом класса. Класс выглядит так

from functools import wraps

class MyClass(object):
    def __init__(self):
        print('Within my class object')

    def my_decorator(func_to_decorate):
        @wraps(func_to_decorate)
        def wrapper(self):
            print('Before the call')

            func_to_decorate(self)

            print('After the function call')
        return wrapper

    @my_decorator
    def print_name(self):
        print('My name is ------ ')

mobj = MyClass()
mobj.print_name()

Работает нормально, я получаю результат, который мне нужен

Before the call
My name is ------ 
After the function call

Но затем, глядя на определение функции декоратора my_decorator, я понял, что метод не принимает то, что метод класса обычно принимает в качестве первого аргумента self

Теперь мой вопрос: какой тип my_decorator? Это метод класса, обычный метод или специальный метод?

Обычно методы внутри класса принимают неявный аргумент self или, если это метод класса, принимают неявный аргумент cls. Декоратор не берет ни того, ни другого.

Может кто-нибудь объяснить, что здесь происходит?


person rgk    schedule 26.07.2014    source источник
comment
Кстати, вы путаете методы класса с методами экземпляра. Обычные методы называются методами экземпляра, поскольку они принимают экземпляр в качестве своего первого аргумента self. Методы класса создаются с помощью декоратора @classmethod и принимают класс в качестве первого аргумента, обычно называемого cls.   -  person Sven Marnach    schedule 26.07.2014
comment
@SvenMarnach Плохо. Спасибо, что поправили меня.   -  person rgk    schedule 26.07.2014


Ответы (1)


Это простая функция, поскольку вы не получаете к ней доступ из класса или экземпляра, поэтому self или cls не требуются для этой функции при использовании внутри определения класса в качестве декоратора. Неявные аргументы вызываются такими функциями только тогда, когда мы обращаемся к ним с помощью класса или экземпляра, потому что доступ к ним через класс или экземпляр возвращает несвязанные и связанные методы, которые представляют собой тонкие оболочки исходной функции.

Если вы переместите декоратор за пределы класса, вы увидите, что он ожидает от вас отправки экземпляра в качестве первого аргумента:

MyClass.print_name = MyClass.my_decorator(MyClass.print_name)
mobj = MyClass()
mobj.print_name()

Ошибка:

MyClass.print_name = MyClass.my_decorator(MyClass.print_name)
TypeError: unbound method my_decorator() must be called with MyClass instance as first argument (got instancemethod instance instead)

Хотя вы можете предотвратить эту ошибку, объявив my_decorator статическим методом, который не ожидает ни self, ни cls, или получить доступ к базовой функции, используя атрибут im_func связанных, несвязанных объектов:

MyClass.print_name = MyClass.my_decorator.im_func(MyClass.print_name)

Вам следует прочитать часть Вызываемые типы в модели данных. страница.

person Ashwini Chaudhary    schedule 26.07.2014