练习一:装饰器实现一个函数计时器
“”"
“”"
1.问题1:被装饰的函数有返回值
2.问题2:如何保留被装饰函数的函数名和帮助信息文档
“”"
import time
import random
import string
li = [random.choice(string.ascii_letters) for i in range(10)]
print(li)
def Timer(fun):
def wrapper(*args,**kwargs):
start_time = time.time()
res = fun(*args,**kwargs)
end_time = time.time()
print('运行时间为: %.5f' %(end_time - start_time))
return res
return wrapper
@Timer
def con_add():
s = ''
for i in li:
s += (i + ',')
print(s)
@Timer
def join_add():
print(','.join(li))
@Timer
def fun_list(n):
return [i * 2 for i in range(n)]
@Timer
def fun_map(n):
return list(map(lambda x:x*2,range(n)))
con_add()
join_add()
print(fun_list(10))
print(fun_map(10))
结果为:
['C', 'R', 'z', 'p', 'z', 'H', 'D', 'V', 'V', 'A']
C,R,z,p,z,H,D,V,V,A,
运行时间为: 0.00002
C,R,z,p,z,H,D,V,V,A
运行时间为: 0.00001
运行时间为: 0.00001
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
运行时间为: 0.00001
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
1.问题1:被装饰的函数有返回值
import time
import functools
def add_log(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
start_time = time.time()
res = fun(*args,**kwargs)
end_time = time.time()
print('[%s] 函数名: %s, 运行时间: %6f,运行返回值结果: %d' %(time.ctime(),fun.__name__,end_time - start_time,res))
return res
return wrapper
@add_log
def add(x,y):
time.sleep(1)
return x + y
add(1,2)
结果为:
[Tue Apr 2 03:50:43 2019] 函数名: add, 运行时间: 1.001367,运行返回值结果: 3
2.问题2:如何保留被装饰函数的函数名和帮助信息文档
(1)导入 functools包,加入 @functools.wraps(fun)
(2)print(xxx.doc) ##帮助信息文档
print(xxx.name) ##函数名
import time
import random
import string
import functools
li = [random.choice(string.ascii_letters) for i in range(100)]
print(li)
def Timer(fun):
"""这是一个装饰器Timer"""
@functools.wraps(fun) ##函数帮助文档
def wrapper(*args,**kwargs):
"""这是一个wrapper函数"""
start_time = time.time()
res = fun(*args,**kwargs)
end_time = time.time()
print('运行时间为: %.5f' %(end_time - start_time))
return res
return wrapper
@Timer
def con_add():
s = ''
for i in li:
s += (i + ',')
print(s)
@Timer
def join_add():
print(','.join(li))
@Timer
def fun_list(n):
"""这是fun_list函数"""
return [i * 2 for i in range(n)]
@Timer
def fun_map(n):
return list(map(lambda x:x*2,range(n)))
print(fun_list.__doc__)
print(fun_list.__name__)
print(time.ctime())
['Z', 'v', 'k', 'L', 'V', 'S', 'G', 'k', 'H', 'P']
这是一个wrapper函数
wrapper
Tue Apr 2 03:49:34 2019
练习二:inspect.getcallargs
import functools
import inspect
def is_admin(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
#inspect.getcallargs返回一个字典,key值是形参,value值
#是对应的实参{'name':'root'}
inspect_res = inspect.getcallargs(fun,*args,*kwargs)
print('inspect的返回值: %s' %inspect_res)
if inspect_res.get('name') == 'root':
res = fun(*args,**kwargs)
return res
else:
print('not root user!')
return wrapper
@is_admin
def add_user(name):
print('添加用户信息...')
def del_user(name):
print('删除用户信息...')
add_user('root')
结果为:
inspect的返回值: {'name': 'root'}
添加用户信息...
练习三: 编写装饰器required_types, 条件如下:
1). 当装饰器为@required_types(int,float)确保函数接收到的
每一个参数都是int或者float类型;
2). 当装饰器为@required_types(list)确保函数接收到的每一>个参数都是list类型;
3). 当装饰器为@required_types(str,int)确保函数接收到的每
一个参数都是str或者int类型;
4). 如果参数不满足条件, 打印 TypeError:参数必须为xxxx类
型
import functools
def required_types(*kinds):
def required_ints(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
for i in args:
if not isinstance(i,kinds):
print('TypeError:参数为',kinds)
break
else:
res = fun(*args,**kwargs)
return res
return wrapper
return required_ints
@required_types(float,float)
def add (a,b):
return a + b
print (add(1.1,1.9))
结果为:3