Почему обернутая функция в этом декораторе запускается автоматически, и ни один из них не вызывается?
Я изучаю, как использовать декоратор в Python 3. Я набрал эти коды в редакторе и нажал кнопку "Выполнить".
log_stat = False
def decorator():
def wrapper(func):
global log_stat
while not log_stat:
username = input("username")
password = input("password")
if username == "123" and password == "456":
func()
log_stat = True
else:
print("try again")
return wrapper
@decorator()
def welcome():
print("welcome")
Я не ожидал, что на экране ничего не будет отображаться, так как думал, что я просто определял функции, а не вызывал или выполнял их. Но python попросил меня ввести имя пользователя и пароль, которые, похоже, действительно запустили упакованную функцию.
Какова реальная причина этого? И как я могу просто определить функцию, не вызывая упакованную?
2 ответа
Декоратор - это вызываемый объект, который принимает класс или функцию и возвращает класс или функцию. Синтаксис декоратора
@decorator # note no ()
def function():
...
То, что вы делаете, звонит decorator
затем, используя результат этого вызова (wrapper
) декорировать welcome
, wrapper
поэтому бежит сразу.
То, что вы намеревались написать, было, вероятно,
def decorator(func):
def wrapper(*args, **kwargs):
global log_stat
while not log_stat:
username = input("username")
password = input("password")
if username == "123" and password == "456":
log_stat = True
return func(*args, **kwargs)
else:
print("try again") # I would raise an exception here
return wrapper
@decorator
def welcome():
print("welcome")
Обратите внимание, что wrapper
принимает аргументы в этой версии. Это потому, что когда вы украшаете welcome
заменяется на wrapper
, Так что если ваш welcome
функция взяла аргументы, ваш wrapper
также придется принять их, чтобы передать их в исходную функцию.
Потому что вы вызвали декоратор при его использовании. Это означает, что он работает во время импорта. Вы должны удалить скобки.
@decorator
def welcome():
print("welcome")
(Можно определить декоратор, который вызывается во время импорта, если он принимает параметры; но для этого необходимо реализовать другой уровень переноса, чтобы функция возвращала декоратор, который, в свою очередь, возвращает функцию, которая переносит оригинал).