今天,当我学习装饰器时,我有一个问题,请看下面的两段代码 代码1:
def log(func):
def wrapper(*args,**kw):
print('call %s():' % func.__name__)
return func(*args,**kw)
return wrapper
@log
def now():
print('2018-8-28')
now()
代码2:
def log(func):
print('call %s():' % func.__name__)
return func
@log
def now():
print('2018-8-28')
now()
print(type(now()))
为什么第一个代码定义了多个包装函数?两种代码的输出是相同的。
在代码2中,我为now函数使用了type
方法来查看其类型,结果类型为None
。
答案 0 :(得分:2)
在函数定义之前使用@log
(或其他装饰器)会调用装饰器函数(在这种情况下为log
),并将装饰函数作为参数,并且将装饰函数替换为装饰函数返回的函数,即,类似于在函数初始声明后执行now = log(now)
。
因此,当装饰函数时,“简短”版本将打印“调用”行一次,然后返回函数本身。另一方面,每次调用该函数时,“ long”版本都会通过返回一个包装原始函数并进行日志记录的新函数来打印“ call”行。
您的输出是相同的,就像您在装饰完函数后立即调用一次函数一样。
答案 1 :(得分:0)
为什么第一个图形定义了多个包装函数?
装饰器已传递其装饰的功能;然后将其封装在wrapper
函数内部,从而进行命名。
图像1 与执行图像2中的操作没有什么不同(如果不需要使用包装功能):
def log(func):
return func('hello there')
@log
def now(msg):
print(msg)
在给定的示例中,虽然在某些情况下需要使用wrapper
函数,但并不需要使用wrapper
。 -注意:包装函数时,您隐式地将一个函数替换为另一个函数。