起因是廖老师的一个作业:
https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014318435599930270c0381a3b44db991cd6d858064ac0000#0
作业:
# -*- coding: utf-8 -*-
"""
Created on Wed Feb 13 19:21:59 2019
@author: chealia
"""
import functools,time
def metric(text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args,**kw):
start=time.time()
f=func(*args,**kw)
print('%s is %s in %s ms'%(func.__name__,text,time.time()-start))
return f
return wrapper
print(type(text))
return decorator if isinstance(text,str) else decorator(text)
@metric
def fast(x, y):
time.sleep(0.0012)
print(x+y)
return x + y
@metric('execute')
def slow(x, y, z):
time.sleep(0.1234)
print(x*y*z)
return x * y * z
f = fast(11, 22)
s = slow(11, 22, 33)
关于那句 return decorator if isinstance(text,str) else decorator(text)的解释:
装饰器的参数传递是按顺序来的。首先是mertic(text)定义中的text,然后是函数func,然后是函数的参数(*args,**kw),即指(x,y)或者(x,y,z)。如果没有text,那么就会把函数名传进去,例如运行结果中的‘
33
fast is in 0.002995729446411133 ms
7986
slow is execute in 0.13919687271118164 ms
如果把这段return的(text)去掉:
return decorator if isinstance(text,str) else decorator(text)
运行结果就会变成:
TypeError: decorator() takes 1 positional argument but 2 were given
因为传入了两个参数(x,y).
还可以试试这样:
import functools,time
def metric(text):
def decorator(func):
print('text: ',text)
print('func: ',func)
@functools.wraps(func)
def wrapper(*args,**kw):
start=time.time()
f=func(*args,**kw)
print('%s is %s in %s ms'%(func.__name__,text,time.time()-start))
return f
return wrapper
print(type(text))
return decorator
@metric
def fast(x):
time.sleep(0.0012)
print(x*x)
return x*x
@metric
def slow(x):
time.sleep(0.1234)
print(x)
return x
f = fast(11)
s = slow(11)
运行结果是:
text:
func: 11
text:
func: 11
它把函数的名字当成metric(text)的text传进去了,再把函数的参数当做decorator(func)的func传进去了!