关于python进阶的方向和知识点很多,今天聊聊装饰器。
过年之前网上逛到一本Python进阶文档,除了一些零散的知识点,里面关于装饰器的讲解挺不错的。
魔法变量args和kwargs
首先 *args
和**kwargs
只有前面的星号才是必须的,args和kwargs是一个通俗的命名约定。
这两个参数适合与参数数量不定的函数调用处理。args用于普通参数,kwargs用于键值对。
1 | def test_var_args(f_args, *args, **kwargs): |
这个特性可以装饰器对函数进行重新封装的时候用到。
函数对象
Python的函数其实本质上就是对象,可以对函数进行二次封装。
1 | def add(a,b): |
引入一个概念,高阶函数,可以接受参数为函数的函数。
高阶函数与装饰器
因此,我们可以在定义一个高阶函数,对接受进来的函数进行修改,重新返回。
1 | def with_log(func): |
上面的with_log就是一个装饰器,对已经定义好的函数进行修饰。在需要装饰的函数定义上加一朵花,然后就可以对这个函数增加一些装饰。
完善的装饰器
上面的装饰器有个问题,我们调用的是add,但是打印出来的函数名字是new_func,这显然不是我们想要的。正确的做法如下
1 | from functools import wraps |
另外还有一个问题。如果要将这个装饰器用到其他函数上,那么里面的参数个数,就不能够写死为add函数的参数。此时,前面讲到魔法变量便排上了用场。
1 | from functools import wraps |
装饰器会引入一个问题,它会允许调用者随意写参数的调用形式,因此在函数实现的时候,如果有必要,需要对参数进行检查。
带参数的装饰器
因为装饰器本身也是函数,装饰器也可以带参数。通过两层的函数定义,可以实现带参数的装饰器,下面直接看一个例子即可。
1 | from functools import wraps |
装饰器是对函数进行二次封装,是一种基础的函数式编程的实现。
总结
魔法变量和函数对象特性为装饰器的实现提供了可能,在具体的使用的时候需要借助functools的wrap来保证内置变量的正确性。二层封装实现了带参数的装饰器。
装饰器是基本的函数式编程,很Pythonic。后续的进阶要针对面向对象概念或者框架进行。