您的位置:首页 > 编程语言 > Python开发

Python 装饰器浅析

2018-02-20 09:35 399 查看
Python 装饰器是 Python 中常常使用到的一种语法糖,它可以大幅度减少重复代码,使用起来十分方便。另一方面,装饰器的定义往往会导致出现函数重重嵌套的情况,这会给装饰器的实现者带来阅读代码的困难。

本文剖析 Python 装饰器的定义与用法。

不带参数的装饰器

我们先来看一下不带参数的装饰器的实现,这种情况比较简单。以下是一个不带参数的装饰器的使用例子:

@decorator
def fun():
print('fun() is called')


前面提到,装饰器只是 Python 提供的语法糖,使用
@decorator
作为装饰器相当于:

def fun():
print('fun() is called')
fun = decorator(fun)


我们再来看一下装饰器
decorator
本身的定义。装饰器可以使用函数实现,也可以使用类来实现,这里我们介绍函数的实现方式。

def decorator(fun):
def decorated_function():
print('before fun, do something')
fun()
print('after fun, do something')
return decorated_function


装饰器
decorator
被定义成一个函数,这个函数返回一个新的函数。同时,我们看到
decorator
接受一个
fun
的形参,
fun
作为一个函数,会在
decorated_function
中被调用。

使用装饰器后,如果调用
fun()
,则会输出:

before fun, do something

fun() is called

after fun, do something

通过装饰器
decorator
,原来的
fun
函数,被赋值成
decorator(fun)
,而
decorator(fun)
会触发
decorator
函数的调用并返回
decorated_function
这个函数。在
decorated_function
中,会先输出
before fun, do something
,然后调用
fun()
,最后输出
after fun, do something


带参数的装饰器

装饰器支持带参数,我们先来看下带参数的装饰器的使用方式。

@cached(5)
def fun():
print('fun() is called')


上面带参数的装饰器的使用,等价于以下的代码:

def fun():
print('fun() is called')
fun = cached(5)(fun)


装饰器
cached
被定义成一个函数,它的定义如下:

def cached(timeout):
def decorator(func):
def decorated_function():
print('before fun, do something, timeout=%d' % timeout)
func()
print('after fun, do something, timeout=%d' % timeout)
return decorated_function
return decorator


cached
是一个函数,它接受一个
timeout
的形参,并返回一个
decorator
的函数。
cached(5)
会进行函数调用且函数的实参为5,并返回
decorator
decorator
也是个函数,
decorator(fun)
(即
cached(5)(fun)
)相当于上面不带参数的装饰器的使用,它返回
decorated_function
这个函数。

看起来有点复杂,实际上,带参数的装饰器只是在不参数的装饰器的基础上再多一层函数的封装而已,多的这层函数是为了将装饰器的参数传递进去。

使用装饰器后,如果调用
fun()
函数,则会输出:

before fun, do something, timeout=5

fun() is called

after fun, do something, timeout=5

参考资料

http://www.lightxue.com/understand-python-decorator-the-easy-way

https://mp.weixin.qq.com/s/98JA68TX9X4j6wPABiMJNA

https://mp.weixin.qq.com/s/Om98PpncG52Ba1ZQ8NIjLA

http://code.oneapm.com/python/2015/04/27/python-decorator-mistake/

http://www.jianshu.com/p/d03e4dfc5a78

http://blog.guoyb.com/2016/04/19/python-decorator/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: