宽屏模式

python学习笔记(6)_装饰器

装饰器

在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)
它可以让某个函数在不做任何代码变动的情况下,增加额外功能;
返回值也是一个函数对象
它经常用于有切面需求的场景;
比如:插入日志、性能测试、事务处理、缓存、权限校验等场景;
一句话,装饰器的作用就是为已经存在的对象添加额外的功能

例如:

def foo():
    print('i`m foo')

现在,有个新需求,需要在函数中插入日志:

def foo():
    print('i`m foo')
    logging.info('foo`s log')

在其他函数,foo1(),foo2(),中也有这样的需求,
如果再在每个函数内写多一个logging就会造成大量代码的重复;
可以定义一个函数,专门处理日志,日志处理完后再执行业务代码;

def my_log(func):
    logging.warn("This is %s`s log" % func.__name__)
    func()
def foo1():
    print('i`m foo1')

my_log(foo1)

虽然这样可以实现,但是每次都需要将一个函数作为参数传给my_log();
而且,这样还破坏了原有的代码逻辑结构(之前是运行foo1(),现在需要运行my_log(foo1));
那么,这时候就需要一个更好的解决方案----装饰器;
请看以下代码:

def my_log(func):
    def wrapper(*args, **kwargs):\
        logging.warn("%s is running" % unc.__name___)
        return func(*args)
    return warpper
def foo1():
    print('i`m foo1')

foo1 = my_log(foo1)
foo1()

其中,my_log就是装饰器,它将执行业务的函数func包裹在函数里面;
看起来就像my_log被装饰了;
上面的例子中,函数进入和退出时,被称为一个横切面(Aspect);
这种编程方式呗称为面向切面的编程(Aspect-Oriented Programming);

装饰器中,@符号是它的语法糖;
在定义函数的时候使用,可以避免再一次赋值操作(为什么呢?foo1 = my_log(foo1));

def my_log(func):
    def wrapper(*args, **kwargs):
        logging.warn("%s is running" % unc.__name___)
        return func(*args, **kwargs)
    return wrappper
    
@my_log
def foo():
    primt('i`m foo')
foo()

如上所示,这样我们就省去了foo = my_log(foo)这一步;
如果有多个函数需要被修饰,直接使用@my_log即可;
不需要重复修改函数,或增加新的封装。
程序可读性和可重复利用性大大提高;
装饰器的方便性,还要归功于python中,函数可以作为参数传递给其他函数;
可以被赋值给其它变量,可以作为返回值;
可以被定义在另一个函数里面;

带参数的装饰器

未完待续。。。

Larwas
请先登录后发表评论
  • latest comments
  • 总共0条评论