Python 装饰器复习
在前段时间的面试中,我被问了一个很基础的问题:decorator怎么写。然而很遗憾的是我当时确实就是写错了。我想这确实是对装饰器理解有误造成的。
为什么使用装饰器
使用装饰器的目的是更好地复用代码。使用装饰器可以在原有函数的基础上添加一些功能而不用对函数进行修改。
错误的写法
当被问及怎么写一个解释器的时候,因为没做好要被问Python问题的准备。然后就写出了下面这个错误的版本:(当时是手写的,因此没有办法执行而看到结果)
1 | def wrapper1(func): |
装饰器是接受一个函数返回一个函数,我以为它的作用是每次都给包上这个函数,从而达到每次都执行的目的。
但是实际如果在解释器中运行的话,就能看到发生了什么事情:
1 | In [1]: def wrapper1(func): |
在定义tempFunc
的时候,可以看到已经有了一个输出,但是使用这个函数的时候却没有输出。
这是我以为会发生的事情,每一次调用tempFunc都会执行下面的这个操作:
1 | wrapper1(tempFunc)() |
如果是这样的话,上面那种写法是没有问题的。
但是实际发生的情况是:
1 | tempFunc = wrapper1(tempFunc) # 相当于只执行一次 |
在知道了原理是这样的之后,我们才能将程序写对。
正确的写法
1 | def wrapper2(func): |
这样我们能得到正确的解释器。
1 | In [8]: @wrapper2 |
这其中用到了一些python可变参数写法,但是其实并不是特别的麻烦。
带参数的装饰器
装饰器也是可以带参数的。我们还是需要返回一个函数,只是这个函数
1 | def wrapper3(text): |
实际使用结果:
1 | In [12]: @wrapper3('hello') |
其实理解起来也并不难,我们对这个函数做的操作是这样的:
1 | tempFunc = ((wrapper3('hello'))(tempFunc))() |
所以我们需要做的是,接受一个参数,返回一个普通的装饰器。然后这个装饰器中又是接受一个函数,返回一个函数的。
总结
想起了当时考官戏谑的眼神……