Python статический метод декоратора с наследованием - PullRequest
0 голосов
/ 19 февраля 2020

Мой случай:

class BaseClass:

    @staticmethod
    def dummy_decorator(fnc):
        def wrapper():
            print('Im so dummy')
        return wrapper


class InheritedClass(BaseClass):
    def __init__(self):
        pass

    def anymethod(self):
        print('hello world')

Когда я смотрю на dir(), я вижу свой staticmethod

>>> c = InheritedClass()
>>> dir(c)
['__doc__', '__init__', '__module__', 'anymethod', 'dummy_decorator']

Кроме того, я могу использовать свой фиктивный оператор как простой staticmethod внутри нового класса , Но когда я пытаюсь использовать его в качестве декоратора - я получаю ошибку

class InheritedClass(BaseClass):
    def __init__(self):
        pass

    @dummy_decorator
    def anymethod(self):
        print('hello world')

>>> NameError: name 'dummy_decorator' is not defined

Почему это так работает? Я знаю, что если я изменю @dummy_decorator на @BaseClass.dummy_decorator - все будет работать, но почему я не могу использовать decorator без ref для родительского класса?

Ответы [ 2 ]

0 голосов
/ 19 февраля 2020

Чтобы понять это правильно, вам нужно понять, как работают class определения. В двух словах, все внутри блока class выполняется так же, как обычный код Python. Каждое имя , которое было создано внутри этого блока class (например, def или присваивание переменных), затем оборачивается в конце блока class и становится атрибутами нового объекта класса. Это выглядит примерно так:

# START CAPTURE
def __init__(self):
    pass

foo = 'bar'
# END CAPTURE

InheritedClass = # OBJECT WITH ATTRIBUTES "CAPTURED" ABOVE AND ADDITIONAL MAGIC

Итак, любой код в блоке class является просто обычным кодом Python. Он еще ничего не «унаследовал». Это «дополнительные маги» c, применяемые к результирующему объекту класса в конце блока class. А поскольку не определено глобальное имя "dummy_decorator", его нельзя называть по этому имени. Он существует как "BaseClass.dummy_decoator", так же как и вне любого блока class.

0 голосов
/ 19 февраля 2020

Причина, по которой это потому, что это метод stati c, относится к классу, как вы выяснили, когда вы положили @BaseClass.dummy_decorator, и он сработал.

Это атрибут класса, поэтому вы не можете просто сослаться на него по dummy_decorator, если не переместите его из класса или не сохраните в глобальном пространстве имен

...