Почему декоратор изменяет тип функции на NoneType

Пытался создать игру в палочки, но столкнулся с такой проблемой, что при применении декоратора функция становится объектом типа NoneType

Вот код:

from functools import wraps

CountOfSticks = int(input("Введите начальное кол-во палочек: "))

name1 = str(input("Введите имя первого игрока: "))
name2 = str(input("Введите имя второго игрока: "))


def funcdeco(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        for n in args:
            if n == name1:
                print(f"Выбирает игрок {name1}")
                result = func(*args, **kwargs)
                print(f"Игрок {name1} выбрал {result}")
                return print("Выбирает следующий игрок!\n")
        for i in args:
            if i == name2:
                print(f"Выбирает игрок {name2}")
                result = func(*args, **kwargs)
                print(f"Игрок {name2} выбрал {result}")
                return print("Выбирает следующий игрок!\n")
    return wrapper()


@funcdeco
def tyanite(name):
    vibor = int(input(f"{name} введите кол-во палочек, которые хотите вытянуть: "))
    global CountOfSticks
    CountOfSticks=CountOfSticks-vibor
    return CountOfSticks


print(type(tyanite))
while CountOfSticks:
    tyanite(name1)
    print(f"Осталось {CountOfSticks} палочек")
    if CountOfSticks == 0:
        print(f"Выйграл игрок {name1}")
        break
    tyanite(name2)
    print(f"Осталось {CountOfSticks} палочек")
    if CountOfSticks == 0:
        print(f"Выйграл игрок {name2}")
        break

print(type(tyanite)) прописал, чтобы проверить сам тип, собственно

Я здесь новенький, поэтому если я не правильно оформил вопрос, то напишите об этом, пожалуйста


Ответы (1 шт):

Автор решения: CrazyElf
def funcdeco(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        ...
    return wrapper()
                  ^^ <- ЭТО ВЫЗОВ ФУНКЦИИ wrapper!

В декораторе возвращать нужно не вызов внутренней функции, а ссылку на неё:

def funcdeco(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        ...
    return wrapper # <- возвращаем ссылку на функцию, так правильно

Из-за скобок у вас из декоратора возвращается то, что возвращает wrapper при вызове, а он у вас не возвращает ничего. В общем-то это довольно типичная ошибка в питоне - возврат результата вызова функции там, где нужно вернуть ссылку на саму функцию. С точки зрения языка обе конструкции вполне легальны, вызов функции вполне может возвращать ссылку на какую-то функцию, поэтому сам питон не видит тут никакой ошибки.

→ Ссылка