引入装饰器
如果想在一个函数执行前后执行一些别的代码,比如打印一点日志用来输出这个函数的调用情况那应该怎么做呢?
#!/usr/bin/env python
# coding=utf-8
def logger(fn): # 函数作为参数即fn可以为任何参数
def wrap(*args, **kwargs): # 可变参数args和kwargs
print('call {}'.format(fn.__name__))
ret = fn(*args, **kwargs) # 函数调用时的参数解构
print('{} called'.format(fn.__name__))
return ret # 返回函数的返回值
return wrap
def add(x, y):
return x + y
logger_add = logger(add)
print(logger_add.__name__)
print(logger_add)
ret = logger_add(3, 5)
print(ret)
#输出结果:
wrap
<function logger.<locals>.wrap at 0x7fba35f4fe18>
call add
add called
8
也可以用以下方式来实现这种效果
@logger
def add(x, y):
return x + y ret = add(3, 5)
print(ret)
# 输出结果:
call add
add called
8
这就是Python装饰器的一个简单使用
什么是装饰器?
装饰器是用于软件设计模式的名称。 装饰器可以动态地改变函数,方法或类的功能,而不必直接使用子类或改变被装饰的函数的源代码。Python装饰器是对Python语法的一种特殊改变,它允许我们更方便地修改函数,方法以及类。
当我们按照以下方式编写代码时:
@logger
def add(x, y):
...
和单独执行下面的步骤是一样的:
def add(x, y):
...
logger_add = logger(add)
装饰器内部的代码一般会创建一个新的函数,利用*args
和**kwargs
来接受任意的参数,上述代码中的wrap()函数就是这样的。在这个函数内部,我们需要调用原来的输入函数(即被包装的函数,它是装饰器的输入参数)并返回它的结果。但是也可以添加任何想要添加的代码,比如在上述代码中输出函数的调用情况,也可以添加计时处理等等。这个新创建的wrap函数会作为装饰器的结果返回,取代了原来的函数。
所以在Python中,装饰器的参数是一个函数, 返回值是一个函数的函数