【Python高级编程】装饰器

38 阅读2分钟

课堂引入

python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能。

授课进程

函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数。

 def get_time():
         now = datetime.now()
 func = get_time
 func()
 print(func())
 '''
 运行结果
 None # 注意这里是因为get_time 没有设置return
 '''

函数对象有一个name属性,可以拿到函数的名字:

>>> func.__name__
'get_time'

丰富原有函数的功能,但又不修改原有函数的功能,这种在代码运行期间动态增加功能的方式,称之为“装饰器”。

现在,对原有的函数增加调用的时候,打印调用日志。本质上,decorator就是一个返回函数的高阶函数。所以,我们要定义一个能打印日志的decorator,可以定义如下:

def log(func):
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper

观察上面的log,因为它是一个decorator,所以接受一个函数作为参数,并返回一个函数。要借助Python的@语法,把decorator置于函数的定义处:

@log
def get_time():
    now = datetime.now()

调用get_now()函数,不仅会运行get_now()函数本身,还会在运行get_now()函数前打印一行日志:call get_time(). 把@log放到now()函数的定义处,相当于执行了语句:

log(get_time)()

上面例子中的装饰器是不是功能太简单了,那么装饰器可以加一些参数吗,当然是可以的,另外装饰的函数当然也是可以传参数的。

def logging(level):
    def outwrapper(func):
        def wrapper(*args, **kwargs):
            print("[{0}]: enter {1}()".format(level, func.__name__))
            return func(*args, **kwargs)
        return wrapper
    return outwrapper
@logging(level="INFO")
def hello(a, b, c):
    print(a, b, c)
hello("hello,","good","morning")

如上,装饰器中可以传入参数,先形成一个完整的装饰器,然后再来装饰函数,当然函数如果需要传入参数也是可以的,用不定长参数符号就可以接收,例子中传入了三个参数。