我正在探索如何在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要求我输入用户名和密码,看来它实际上已经运行了包装功能。
真正的原因是什么?以及如何在不触发包装函数的情况下定义函数?
答案 0 :(得分:3)
装饰器是可调用的,它接受一个类或函数并返回一个类或函数。装饰器语法为
@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
也必须接受它们才能将其传递给原始函数。
答案 1 :(得分:1)
因为您在使用装饰器时已将其调用。这意味着它在导入时运行。您应该删除括号。
@decorator
def welcome():
print("welcome")
(可以定义一个在导入时被调用的装饰器,因为它接受参数;但是要这样做,您必须实现另一层包装,以便该函数返回一个装饰器,该装饰器又返回一个函数包裹原始文件。)