印象笔记复制过来格式惨不忍睹,装饰器的知识是从赖大那里偷来的,推荐赖大的博客:http://mingxinglai.com
1.装饰器的概念
2.装饰器的四个注意事项
3.装饰器的缺点
装饰器的概念
1.Python2.4开始提供了装饰器(decorator),装饰器作为修改函数的一种便捷方式,为程序员编写程序提供了便利性和灵活性。
装饰器的本质上就是一个函数,这个函数接收其他函数作为参数,并将其以一个新的修改后的函数进行替换。
装饰器是Python提供给我们的语法糖
def bread(func):
def wrapper():
print "-------"
func()
print "-------"
return wrapper
sandwich_copy = bread(sandwich)
sandwich_copy()
def bread(func):
def wrapper():
print "-----"
func()
print "-----"
return wrapper
@bread
def sandwich(food="--ham--"):
print food
2.涉及到几个知识点:
函数嵌套
函数就是对象(函数对象),可以随意传递
语法糖:语言自身提供,用更加简便的方式表示某种行为
3.装饰器的使用场景:
1.注入参数(提供默认参数,生成参数)
2.记录函数行为(日志、缓存、计时)
3.预处理/后处理(配置上下文)
4.修改调用时的上下文(线程异步或者并行,类方法)
benchmark
import time
def benchmark(func):
def wrapper(*args,**keargs):
t = time.clock()
res = func(*args,**kwargs)
print(func.__name__,time.clock() -t)
return res
return wrapper
装饰器的注意事项
1.函数的属性变化
2.使用inspect获取函数参数
3.多个装饰器的调用顺序
4.给装饰器传递参数
1.如果不实用@functools.wraps(f),函数的属性会丢失
4 from __future__ import print_function
5 import functools
6
7 def is_admin(f):
8 @functools.wraps(f)
9 def wrapper(*args,**kwargs):
10 if kwargs.get('username') != 'admin':
11 raise Exception('This user is not allowed to get food')
12 return f(*args,**kwargs)
13 return wrapper
14
15 def foobar(username = 'someone'):
16 '''Do crazy stuff'''
17 pass
18
19 @is_admin
20 def barfoo(username = 'someone'):
21 '''Do crazy stuff'''
22 pass
23
24 print(foobar.func_doc)
25 print(foobar.__name__)
26 print(barfoo.func_doc)
27 print(barfoo.__name__)
2.使用inspect获取函数参数
inspect.getcallargs(f,*args,**kwargs)自动推断参数对应位置,并总是返回一个字典,这个字典包含了所有的参数
3.多个装饰器的调用顺序,越靠近函数的越先调用
4.给装饰器传递参数:三层封装即可
2 from __future__ import print_function
3
4 def times(length=2):
5 def decorator(func):
6 def wrapper(*args,**kwargs):
7 for i in range(length):
8 func(*args,**kwargs)
9 return wrapper
10 return decorator
11
12 @times(5)
13 def sandwich():
14 print('beef')
15
16 sandwich()
装饰器的缺点:
1.装饰器封装的越多,性能就越差,但是一般易用性会更好
2.封装越复杂,越难以调试
3.只能装饰,不能反装饰
装饰器的概念 | 装饰器的四个注意事项 | 装饰器的缺点 |
装饰器的四个注意事项:
函数属性的变化 | 使用inspect获取函数参数 | 多个装饰器的调用顺序 | 给装饰器传递参数 |