python小白-day4装饰器
装饰器
代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志、性能测试、事务处理等。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
其实弄明白了python中的嵌套函数(也就是所谓的闭合函数)之后,再想搞懂python装饰器就简单多了。总之python装饰器不过就是一个针对嵌套函数的语法糖 。它的作用就是在函数调用方法不变的情况下,把此函数包装成另一个函数来使用。
一、首先来大致了解一下嵌套函数
被嵌套与一层函数中的二层函数可以记录上上一层函数作用域中的变量。
|
1
2
3
4
5
6
7
|
def foo(a): def subfoo(b): return(b + a) return(subfoo)f = foo('content') #由于foo返回的是subfoo,所以f是对subfoo的引用print(f('sub_')) #因为subfoo记录了foo的参数变量'content',所以返回值为'sub_content' |

二、嵌套函数变种装饰器
以下两段代码作用是相同的
|
1
2
3
4
5
6
7
8
9
10
|
def action(x): return(x)def action_pro(n): def warpper(x): return(n(x) * x) return(warpper)action = action_pro(action) #第一个action为自定义的伪装变量,第二个action为上边定义的action函数print(action(3)) #此函数实际warpper(3),返回值为9 |

将上面代码改写
|
1
2
3
4
5
6
7
8
|
def action_pro(n): def warpper(x): return(n(x) * x) return(warpper)@action_pro #用action_pro函数把action包装成warpperdef action(x): return(x)print(action(3)) #此函数实际warpper(3),返回值为9 |

如果装饰器本身需要传入参数,那就需要编写一个返回装饰器的函数,无参数的装饰器就是把把sum函数装饰为一个新的函数。带参数的装饰器是什么样的呢?带参数的装饰器先处理参数,然后再生成一个新的装饰器函数,最后把新函数起个别名,写出来会比较复杂。代码实现如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
def before(): print('before')def after(): print('after')def filter(before_fun,after_fun): def outer(main_fun): def wrpper(*args,**kargs): before_fun() main_fun() after() return wrpper return outer@filter(before,after)def index(): print('index')index() |

还有没有办法实现即支持不带参数,又支持带参数的装饰器呢(代码没看懂,需要仔细研究)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
import functoolsdef log(argument): if not callable(argument): def decorator(function): @functools.wraps(function) def wrapper(*args, **kwargs): print('before function [%s()] run, text: [%s].'%(function.__name__, argument)) rst = function(*args, **kwargs) print('after function [%s()] run, text: [%s].'%(function.__name__, argument)) return rst return wrapper return decorator def wrapper(*args, **kwargs): print('before function run.') argument(*args, **kwargs) print('after function run.') return wrapper@logdef func(): print('func() run.')@log('log text')def func1(): print('func() run without parameter')if '__main__' == __name__: func() func1() |

浙公网安备 33010602011771号