不带参数的装饰器
核心思想就是设计模式中的装饰者模式。
按照 Java 中的写法,我们一般是这么做的:
定义一个专门处理日志打印的函数,接受需要处理的函数:
1 | def print_log(func): |
使用:print_log(func)
其实在我( Java 程序员眼中)看来,这已经是非常的方便了,而且也没有破坏原函数的结构。
但是,对于 Python 来说还远远不够,它追求的是依然运行 func()
并且在不改变其内部结构的基础上扩展别的功能。
且 Python 还用语法糖简化了其使用过程。不过首先,也是非常关键的一点是要理解闭包的概念,上一篇的 Python 高级特性中介绍有提过。
用代码说话,下面就是一个简单的装饰器:
1 | def log(f): |
第一眼看真的是一脸懵逼,我花了大量的时间想弄清楚 return f(x)
到底是什么意思,有什么用,这个参数 x
又是什么意思。
于是我改造了一下,去掉了那个 return
和 x
,写成非常好理解的形式:
1 | def log(f): |
运行:
call funcc()...
i am funcc
并没有问题。函数 log()
的用意是接收一个函数,在不改变传进来的函数的情况下,打印该函数的信息。
print 'call ' + f.__name__ + '()...'
这行就是打印原函数的名称,也就是装饰器的装饰物。
最后就是赋值给原先的函数。
上面那个只是没有参数的函数的装饰,对于有参数的函数,我们需要这么写:
1 | def log(f): |
这个其实就是比较标准的 Python 装饰器了,除了一个地方,就是那个 return
。暂且我就当成是为了规范吧,因为对于函数 fn
来说好像通过 return
来获取传进来的函数 f
确实是没有用的啊。
上面那个代码,我运行之后发现,没有 return 是行不通的,所以这个 return 还是必须要加上去的,那为什么没有参数的就行的通呢
我好像突然想明白了 = =
理解了上面的代码之后,关于装饰器的语法糖就很好理解了,每次写:
1 | funcc = log(funcc) |
肯定是觉得有点烦人的,所以 Python 提供了便捷方式:
要被装饰的函数可以这么写:
1 |
|
之后使用就是直接:funcc()
就好了。
这个 @ 后面跟的就是之前自己定义的装饰器的函数名称。
带参数的装饰器
这里说的参数指的是装饰器上面的参数,不是装饰器接受的函数是否带参数。
使用带参数的装饰器就是在外面再包一层:
1 | def log(text): |
那个 text
就是装饰器的参数,可以根据它来做增加一些业务逻辑,用法:
1 |
类装饰器
相比函数装饰器,类装饰器更强大。。。
之后再补充吧,要炸了。