Ошибка "TypeError: 'NoneType' object is not callable" при использовании декоратора с параметрами
Новичок в декораторах.
main.py:
def decoration(name):
def wrapper(func):
func(name)
return wrapper
my_list = []
hello.py:
from main import decoration, my_list
@decoration(name="Артур")
def func(name):
my_list.append(name)
func()
При запуске hello.py выходит ошибка:
TypeError: 'NoneType' object is not callable
Что делать?
Ответы (1 шт):
Есть две большие разницы:
@decoration- просто декоратор@decoration(name="Артур")(или@decoration()) - вызов функции, которая должна вернуть декоратор
В вашем случае decoration вызывается с параметром name="Артур", потом то, что она вернула (функцию wrapper), интерпретатор пытается использовать как декоратор - т.е. передать туда декорируемую функцию (func), и этот декоратор должен вернуть функцию-обертку (которая должна заменить декорируемую функцию), но он сразу вызывает функцию func, и ничего не возвращает, что для Python означает, что возвращено None. Получается, что в результате декорирования функция func была заменена на None, в итоге при попытке вызова этой функции вылетает ошибка TypeError: 'NoneType' object is not callable.
Чтобы работало правильно, нужно сделать чтобы функция decoration возвращала декоратор (который уже в свою очередь будет возвращать функцию wrapper):
def decoration(name):
def decorator(func):
# wrapper без параметров, т.к. в конце func() вызывается без параметров
def wrapper():
func(name)
return wrapper
return decorator
my_list = []
@decoration(name="Артур")
def func(name):
my_list.append(name)
func()
print(my_list) # выведет ['Артур']
К прочтению:
- Понимаем декораторы в Python'e, шаг за шагом. Шаг 1
- Понимаем декораторы в Python'e, шаг за шагом. Шаг 2 (случай декоратора с параметрами рассматривается в разделе "Вызов декоратора с различными аргументами")