python中提供的装饰器(decorator)作为修改函数的一种便捷的方式。
装饰器本质上就是一个函数,这个函数接受其他的函数作为参数,并将其以一个新的修改后的函数进行替换。
(一)我们首先定义一个最简单的函数
1 # -*- coding: utf-8 -*- 2 """ 3 Created on Mon Oct 26 18:00:41 2015 4 @author: zenwan 5 """def square_sum(a, b): 6 return a**2 + b**2
(二)定义一个装饰函数,使用语法糖@来装饰函数
使用语法糖@来装饰函数,相当于square_sum = deco(square_sum)
但发现新函数只在第一次被调用,且原函数多调用一次。
示例代码:
1 # -*- coding: utf-8 -*- 2 """ 3 Created on Mon Oct 26 18:00:41 2015 4 5 @author: zenwan 6 """ 7 8 9 def deco(fun): 10 print "hello" 11 return fun 12 13 14 @deco 15 def square_sum(a, b): 16 return a**2 + b**2 17 18 19 print square_sum(3, 4) 20 print square_sum(3, 4) # 新函数只在第一次被调用,且原函数多调用了一次
运行结果:
hello 25 25
(三)使用内嵌的包装函数来确保每次新的函数都可以被调用
注意:内嵌包装函数的形参和返回值与原函数一样,装饰函数返回内嵌包装函数对象
1 # -*- coding: utf-8 -*- 2 """ 3 Created on Mon Oct 26 18:00:41 2015 4 5 @author: zenwan 6 """ 7 8 9 def deco(fun): 10 def _deco(a, b): 11 print "hello" 12 ret = fun(a, b) 13 return ret 14 return _deco 15 16 17 @deco 18 def square_sum(a, b): 19 return a**2 + b**2 20 21 print square_sum(3, 4) 22 print square_sum(3, 4)
运行结果:
hello 25 hello 25
(四) 参数数量不确定的函数进行装饰
inspect.getcallargs 返回一个将参数名字和值作为键值对的字典,这意味着我们的装饰器不必检查参数是基于位置的参数还是基于关键字的参数,而只需要在字典中即可。
示例代码:
1 # -*- coding: utf-8 -*- 2 """ 3 Created on Mon Oct 26 18:00:41 2015 4 5 @author: zenwan 6 """ 7 import inspect 8 import functools 9 10 def deco(fun): 11 @functools.wraps(fun) 12 def _deco(*args, **kwargs): 13 fun_args = inspect.getcallargs(fun, *args, **kwargs) 14 print fun_args 15 print "hello" 16 return fun(*args, **kwargs) 17 return _deco 18 19 20 @deco 21 def square_sum(a, b): 22 return a**2 + b**2 23 24 print square_sum(3, 4) 25 print square_sum(3, 4)
运行结果:
{'a': 3, 'b': 4} hello 25 {'a': 3, 'b': 4} hello 25
(未完待续)