Python装饰器

百般思念 提交于 2020-03-07 06:59:38

现有如下函数:

def fun1():
    print('...fun1()...')

def fun2():
    print('...fun2()...')

#调用函数
fun1()
fun2()

 

需求:需要给以上两个函数添加记录日志功能

方法一:函数调用

def logging():
    print('...logging...')

def fun1():
    print('...fun1()...')
    logging()

def fun2():
    print('...fun2()...')
    logging()

#调用函数
fun1()
fun2()

 分析:上面这种方式适合少量函数调用,如果有n个地方需要调用logging()函数,那么得手动调用n次,比较麻烦,而且在fun1()中调用loggin()也相当于修改了fun1()的内容。

 

方法二:高阶函数(函数名作为参数传递给另一个函数)

def logging(fun):
    fun()
    print('...logging...')

def fun1():
    print('...fun1()...')


def fun2():
    print('...fun2()...')


#调用函数
logging(fun1)
logging(fun2)

 分析:该方法是高阶函数的用法,将函数名当做参数传递给另一个函数,优点是没有修改源代码,缺点是该方法修改了调用的方式。

 

方法三:高阶函数(返回值中包含函数名)

def logging(fun):
    print('...logging...')
    return fun


def fun1():
    print('...fun1()...')


def fun2():
    print('...fun2()...')


#调用函数
fun1 = logging(fun1)
fun2 = logging(fun2)
fun1()
fun2()

 分析:该方法的优点是没有改变原有函数的调用方式,但是改变的原有输出顺序。

 

方法四:嵌套函数

def logging(fun):
    def dec(fun):
        return fun()
    dec(fun)
    print('...logging...')


def fun1():
    print('...fun1()...')


def fun2():
    print('...fun2()...')


#调用函数
logging(fun1)
logging(fun2)

 分析:该方法优点是没有修改源代码,但是调用方式改变了。

 

总结:

如果需要不修改源代码、不修改调用方式,则需要使用高阶函数+嵌套函数一起,由此引入了装饰器的概念。

 

 

装饰器

定义:本质是函数(装饰其他函数),就是为其他函数添加附加功能。

原则:1.不能修改被装饰函数的源代码

   2.不能修改被装饰函数的调用方式

 

装饰器知识储备:

1.函数即“变量”

2.高阶函数
  a:函数名作为实参传给另一个函数(在不修改源代码的情况下为其新增功能)
  b:返回值中包含函数名(不修改函数的调用方式)

3.嵌套函数

高阶函数+嵌套函数=>装饰器

 

使用高阶函数+嵌套函数修改上面需求:

def logging(fun):
    def dec():
        fun()
        print('...logging...')
    return dec


def fun1():
    print('...fun1()...')


def fun2():
    print('...fun2()...')


#调用函数
fun1 = logging(fun1)
fun2 = logging(fun2)
fun1()
fun2()

 

装饰器语法糖:即在函数前使用@函数名

使用语法糖修改以上代码:

def logging(fun):
    def dec():
        fun()
        print('...logging...')
    return dec

@logging
def fun1():
    print('...fun1()...')

@logging
def fun2():
    print('...fun2()...')


#调用函数
fun1()
fun2()

如上案例中的@logging可以理解为:fun1 = logging(fun1)

 

案例:无参装饰器与有参装饰器

无参装饰器

def fun(func):
    def dec():
        func()
        print('...新增功能...')
    return dec

@fun
def foo():
    print('...test1()...')

foo()

 

def fun(func):
    def dec(x,y):
        func(x,y)
        print('...新增功能...')
    return dec

@fun
def foo(x,y):
    print(x+y)
    print('...test1()...')



foo(5,3)

 

有参装饰器:

def out_fun(m,n):
    def in_fun(fun):
        def dec(x,y):
            fun(x,y)
            print('...新功能...')
            print("m*n=%s"%(m*n))
        return dec
    return in_fun


@out_fun(2,6)
def foo(x,y):
    print(x+y)
    print('...test1()...')



foo(5,3)    # out_fun(2,6)(foo)(5,3)

'''
8
...test1()...
...新功能...
m*n=12
'''

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!