学习目标:

装饰器、切面编程,实际使用体会。
纸上学来终觉浅


装饰器和切面编程:

常见的函数,我们一般的返回值一个常见的数值或者列表,比如:

def mysum(a,b):return a + b
result = mysum(1,2)
print(result)

mysum函数返回的是整数1+2的值,为3.
但是python神奇的地方就是,函数的返回值,可以是另一个函数。比如:

def mysum_log():print('input  two number for sum ')def mysum(a,b):return a + breturn mysum
mysum2= mysum_log()
print(mysum2(1,2))

这样,mysum_log的函数值是一个函数,赋给了变量mysum2,然后print直接用mysum2(1,2)就可以运行函数.此时的mysum2函数有点类似于mysum的功能,但是增加了print功能。
运行结果:

input  two number for sum
3

我们其实可以把变量mysum2直接改成mysum,改一下名字而已,结果就有点神奇了:

def mysum_log():print('input  two number for sum ')def mysum(a,b):return a + breturn mysum
mysum= mysum_log()
print(mysum(1,2))

这样我们看起来像调用了mysum函数,但实际上我们还多了打印日志的print功能。业界成这个叫闭包–鬼知道为啥要叫这么个名字,还以为包pi有关。
这有什么用呢?单纯看没啥用,但是当这个mysum方式最初是别人写的,而且别人不愿意改他的函数,可以通过这种方式丰富函数的功能。
举个例子,隔壁老王写了个函数:

def laowangsum(a, b):return a ^ 2 + b ^ 2

laowangsum的功能是求平方和,但是没有解释,会让人产生误解,你叫老王修改函数,增加注释,他懒不愿意动,怎么办?
此时你想到能不能偷梁换柱,帮他增加点注释,让你的函数调用laowangsum会添加注释log。于是:

def laowangsum(a, b):return a ^ 2 + b ^ 2def mysum_log():print('老王写的sum函数,实际是两个数平方和 ')return laowangsumlaowangsum = mysum_log()
print(laowangsum(1, 2))

你调用的laowangsum函数,实际上多运行了你的注释,偷偷改了老王的函数的功能。这个是闭包的作用。
另一个需求:我们要求对每个函数都打印出日志信息,以便于错误时定位是哪个函数出了问题。或者进行函数大屏监控,怎么办?
为每个函数都加入一个写log的代码?重复性太高,我们想办法抽象起来,既然闭包可以改变函数功能,那用闭包就可以实现,但是现在的闭包需要写明具体函数,不可能以后新增一个函数都去改一下闭包函数。此时就需要装饰器,也叫切面编程。简单来讲,我把一个代表函数的变量传进闭包函数,然后这个闭包函数就可以自适应传进去的函数,自动调用它,不用每次新增函数都去修改闭包,只用调用一次闭包函数即可。

import functoolsdef log_decorator(function):@functools.wraps(function)def wrapper(*args,**kwargs):print('log begin')function(*args,**kwargs)print('log end')return wrapper

比如老王的函数定义时,加上一个@log_decorator,就可以自动帮他写日志,他不用管日志这块:

import functoolsdef log_decorator(function):@functools.wraps(function)def wrapper(*args,**kwargs):print('log begin')result = function(*args,**kwargs)print('log end')return resultreturn wrapper@log_decorator
def laowangsum(a, b):return a ^ 2 + b ^ 2print(laowangsum(1, 2))

运行结果:

log begin
log end
7

可以看到老王虽然自己只实现了加法逻辑,但是函数运行时,却自动多了写日志的功能,就像函数被砍了两刀,自动加上了写log的功能一样。所以叫切面编程。
而且用print(laowangsum.name)打印出来,laowangsum确实就是老王自己定义的函数,名字没有变化,没有被偷梁换柱,因为是@functools.wraps(function)的原因。


装饰类:

除了函数,还可以用装饰类,大同小异。把函数替换成类

class log:def __init__(self,func):self.func = funcself.num_calls = 0    #函数调用次数def __call__(self, *args, **kwargs):self.num_calls += 1print('number of calls is :{}'.format(self.num_calls))return self.func(*args, **kwargs)@log
def example():print('I am being called')example()
example()
example()

结果:

number of calls is :1
I am being called
number of calls is :2
I am being called
number of calls is :3
I am being called

log类自动帮助统计了函数被调用次数。


结论:

装饰器经常用在:
1、 写日志
2、统计运行时间
3、 校验输入数据的有效性和用户认证等

python进阶:搞懂装饰器和切面编程相关推荐

  1. Python 进阶_闭包 装饰器

    目录 目录 闭包 函数的实质和属性 闭包有什么好处 小结 装饰器 更加深入的看看装饰器的执行过程 带参数的装饰器 装饰器的叠加 小结 装饰器能解决什么问题 小结 闭包 Closure: 如果内层函数引 ...

  2. 【python进阶】_装饰器

    装饰器本身是一个函数. 需求:在下面返回时间的函数前面都在开头加上:当地时间 import time def getXXXTime():print()return time.strftime('%Y_ ...

  3. 设计模式系列:搞懂装饰器模式,增加自身技能

    装饰器模式的定义:指在不改变原有对象的基础上,动态地给该对象增加一些额外的功能的模式,属于对象结构型模式. 装饰器模式的核心在于类的扩展,通过装饰器模式可以透明且动态的扩展类的功能. 装饰器模式的结构 ...

  4. 一篇文搞懂《AOP面向切面编程》是一种什么样的体验?

    写在前面 hello,大家好,我是灰小猿,一个超会写bug的程序猿! 近期一直在准备秋招和技术,所以写文的频率有些下降,但是这也依然阻挡不了我要和大家一起分享技术的热情呀. 之前在专栏<SSM编 ...

  5. python进阶(小白也能看懂)——装饰器浅谈(一)

    python进阶(小白也能看懂)--装饰器(一) 第四篇 文章目录 python进阶(小白也能看懂)--装饰器(一) 1.函数基础知识 例子1.1 例子1.2 例子1.3 例子1.4 2.不带参数的装 ...

  6. python重难点之装饰器详解

    背景 虽然之前看过装饰器的相关内容,但是今天想起来,一直没有好好总结一下,所以特地记录下关于装饰器的一系列用法. 要想理解装饰器首先要明确颇python中的三个概念: 1.一切函数皆为对象 2.高阶函 ...

  7. python装饰器与闭包_python中闭包和装饰器的理解(关于python中闭包和装饰器解释最好的文章)。...

    转载:http://python.jobbole.com/81683/ 呵呵!作为一名教python的老师,我发现学生们基本上一开始很难搞定python的装饰器,也许因为装饰器确实很难懂.搞定装饰器需 ...

  8. python闭包和装饰器的区别_python中闭包和装饰器的理解(关于python中闭包和装饰器解释最好的文章)。(转)...

    呵呵!作为一名教python的老师,我发现学生们基本上一开始很难搞定python的装饰器,也许因为装饰器确实很难懂.搞定装饰器需要你了解一些函数式编程的概念,当然还有理解在python中定义和调用函数 ...

  9. Python中的decorator装饰器使用方法

    装饰器的运用是Python编程中的一项高级技巧,这里由浅入深,整理了12步入门Python中的decorator装饰器使用方法,需要的朋友可以参考下 装饰器(decorator)是一种高级Python ...

最新文章

  1. SDWAN分支解决方案:sdwan能用于多分支的企业吗?
  2. HK-2000 数采仪系统说明之 5.H2000SService程序调用说明
  3. 虚方法(virsual method)
  4. 冒泡排序法和选择排序法
  5. 模式串匹配的BF算法和KMP算法
  6. WEB安全第六篇--千里之外奇袭客户端:XSS和HTML注入
  7. php缓存技术基础知识
  8. Dubbo整合Nacos
  9. c语言pipe函数,pipe 函数 (C语言)
  10. 分布电容对小信号的干扰解决方案
  11. HTML5开发工具有哪些?
  12. Python爬取房价
  13. 从字节跳动离职后,拿到探探、趣头条、爱奇艺、小红书、15家公司的 offer
  14. 'PRIMARY' 文件组已满。请删除不需要的文件
  15. Idaily 知乎日报APP
  16. NPDP在国内的含金量
  17. 郑林楷计算机系姚班,郑林楷为什么被清华录取 郑林楷在清华很厉害吗
  18. 基础贵金属白银技术分析(指标工具篇)
  19. 【蒸馏+剪枝】(一)Cascaded channel pruning using hierarchical self-distillation
  20. 如何学python新手入门_如何学习Python,以及新手如何入门?

热门文章

  1. ensp 查看配置命令
  2. 电脑显示计算机无法显示,如果计算机无法打开怎么办?
  3. 微信小程序隐藏滚动条的方法,以及禁止上下滑动的方法
  4. python中什么是实例-在Python中使用’__rsub__’方法的典型实例是什么?
  5. java开发环境jdk1.8_linux 搭建 jdk1.8 java开发环境
  6. JAVA-基础(查找文件夹内文件)
  7. 魔兽老玩家无需购买《燃烧远征》资料片序列号
  8. 嵌入式Linux系统运行流程图
  9. Linux Shell之一 Shell简介
  10. 【实验】给指定的并且已登陆系统的用户发信息