1 装饰器
1.2 函数装饰器
所谓的装饰器,其实是通过装饰器函数,来修改原函数的一些功能,而原函数本身并不进行修改。 下面的示例中,使用装饰器在原函数前进行打印语句。
import functools
def my_decorator(func):
@functools.wraps(func)
def wrapper(*args,**kwargs):
print('this is a wrapper')
func(*args)
return wrapper
@my_decorator
def greet(name):
print('welcome {}!'.format(name))
@my_decorator
def greet_two(name1,name2):
print('welcome {} and {}!'.format(name1,name2))
greet([5,24,2])
greet_two([5,24,2],'234')
print(greet.__name__)
print(help(greet))
this is a wrapper
welcome [5, 24, 2]!
this is a wrapper
welcome [5, 24, 2] and 234!
greet
Help on function greet in module __main__:
greet(name)
None
使用装饰器将会修改原函数的元信息,我们可以通过系统装饰器functools.wraps来保持元信息。
1.2 类装饰器
"""
类装饰器的使用
"""
class Count():
def __init__(self,func):
self.func=func
self.num=0
def __call__(self, *args, **kwargs):
self.num+=1
print('num:{}'.format(self.num))
self.func(*args,**kwargs)
@Count
def example(message):
print('message:{}'.format(message))
example('hello')
example('nihao')
num:1
message:hello
num:2
message:nihao
1.3 使用多个装饰器
我们可以对一个函数使用多个装饰器,顺序为从内到外。
import functools
def decorator1(func):
@functools.wraps(func)
def wrapper(*args,**kwargs):
print('decorator one')
func(*args,**kwargs)
return wrapper
def decorator2(func):
@functools.wraps(func)
def wrapper(*args,**kwargs):
print('decorator two')
func(*args,**kwargs)
return wrapper
@decorator1
@decorator2
def greet(message):
print('message:',message)
greet('hello world')
decorator one
decorator two
message: hello world
1.4 案例
1.4.1 案例1-发表评论
在博客网站或是视频网站发表评论前,我们要先检测用户是否登录,确认登陆后才能发表评论。在此使用装饰器进行登陆的检测。
"""
用装饰器实现:
发表评论前检测是否登录,已登录则发表评论,否则抛出异常
"""
import functools
def check_user_logged_in(request):
return 1 if request>10 else 0
def authenticate(func):
@functools.wraps(func)
def wrapper(*args,**kwargs):
request=args[0]
if check_user_logged_in(request):
func(*args,**kwargs)
else:
raise Exception('Authentication failed')
return wrapper
@authenticate
def post_comment(request, comment):
print('comment successfully:',comment)
post_comment(11,'what a wonderful blog!')
comment successfully: what a wonderful blog!
1.4.2 案例2-记录执行时间
通过装饰器,我们可以记录任意函数的执行时间。
"""
案例2:使用装饰器实现测试任意函数的执行时间
"""
import functools
import time
def log_execute_time(func):
@functools.wraps(func)
def wrapper(*args,**kwargs):
start=time.time()
func(*args,**kwargs)
end=time.time()
print('time cost:%.2f' %(end-start))
return wrapper
@log_execute_time
def calculate_similarity():
count=1
for i in range(int(1e6)):
count+=1
calculate_similarity()
time cost:0.08
1.4.3 案例3-参数合理性检测
在训练神经网络模型时,这个过程往往是非常耗时的,如果花费了几个小时,最后因为参数的不合理而产生报错,就会对资源造成极大的浪费。 在此我们使用装饰器对训练参数进行合理性检测。
"""
在神经网络模型进行训练前,进行参数合理性检查
"""
import functools
def validation_check(func):
@functools.wraps(func)
def wrapper(*args,**kwargs):
for idx,param in enumerate(args):
if not isinstance(param,float):
raise Exception('Parameter format wrong in pos:{}'.format(idx+1))
for idx,key in enumerate(kwargs):
if key=='optimizer' and kwargs[key] not in ['Adam','SGD']:
raise Exception('Keyword parameter format wrong in pos:{}'.format(idx+1+len(args)))
func(*args,**kwargs)
return wrapper
@validation_check
def neural_network_training(l2,lr,dropout,optimizer='SGD'):
print('start training...')
print('l2:{}'.format(l2))
print('learning rate:{}'.format(lr))
print('dropout rate:{}'.format(dropout))
print('optimizer:{}'.format(optimizer))
neural_network_training(0.5,0.001,0.2,optimizer='SGD')
start training...
l2:0.5
learning rate:0.001
dropout rate:0.2
optimizer:SGD
|