博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python装饰器
阅读量:4921 次
发布时间:2019-06-11

本文共 2514 字,大约阅读时间需要 8 分钟。

现有如下函数:

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 fundef 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 decdef 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@loggingdef fun1():    print('...fun1()...')@loggingdef fun2():    print('...fun2()...')#调用函数fun1()fun2()

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

 

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

无参装饰器

def fun(func):    def dec():        func()        print('...新增功能...')    return dec@fundef foo():    print('...test1()...')foo()

 

def fun(func):    def dec(x,y):        func(x,y)        print('...新增功能...')    return dec@fundef 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'''

 

转载于:https://www.cnblogs.com/jmwm/p/9759251.html

你可能感兴趣的文章
9 个超酷的深度学习案例
查看>>
css经典布局—stick footer布局
查看>>
div学习之div中dl-dt-dd的详解
查看>>
linux磁盘的两种分区方法【MBR(Master Boot Record)和GPT(GUID Partition Table)】
查看>>
当在hive中show table …
查看>>
随机森林(Random Forest)
查看>>
[转载]/etc/security/limits.conf解释及应用
查看>>
Spring 之 BeanFactory 源码 - 抽象/类 分析
查看>>
Python的math模块
查看>>
Linux下gcc相关
查看>>
获取URL的参数
查看>>
iphone真机(越狱)通讯录导入进模拟器
查看>>
剑指offer-删除链表中重复的结点
查看>>
mybatis自动生成mapper,dao映射文件
查看>>
IntelliJ IDEA 注册码
查看>>
C 调用数学函数pow时遇到 undefined reference [已解决]
查看>>
IDEA01 创建java项目、创建web项目
查看>>
Springboot21 整合redis、利用redis实现消息队列
查看>>
AJAX 总结
查看>>
[转]WPF中对Excel文件的导入导出操作详解
查看>>