老司机教你 5 分钟读懂 Python 装饰器
1. 写在前面
在介绍python装饰器之前,首先介绍python的一个概念,对象。在python里,所有的一切皆对象。常用的python对象有整型对象,浮点型对象,字符串对象,列表对象,元组对象,字典对象等。其中一个比较特殊的对象是函数对象。
num1 = 1 # 定义了一个整型对象,num1引用了这个对象str1 = "aaa" # 定义了一个字符串对象,str1引用了这个对象list1 = [1,2,3] # 定义了一个列表对象,list1引用了这个对象def my_func() # 定义了一个函数对象print "hello world"func1 = my_func # func1引用了这个函数对象
以一个普通函数为例。
def my_func(name):return "name is {}".format(name)
这里我们定义了一个名为my_func的函数,传入一个字符串对象作为函数的参数,然后返回另一个字符串对象。在上面已经介绍过了,在python中,一切皆对象。那如果我们把一个函数对象作为参数传入,然后返回另一个函数会怎么样呢?这就是装饰器了。
2. 基础装饰器
接着上面的疑问,我们写一个这样的函数。
def add(a, b): # 定义了一个函数对象return a + bmyadd = add # myadd引用了这个函数对象def decorator1(func): # 定义了一个函数对象decorator1,所需参数也是一个函数对象def log(*args, **kwargs): # 在函数内又定义了一个新的函数对象logreturn func(*args, **kwargs)return log # 返回这个log函数对象mydecorator = decorator1(myadd) # 调用函数decorator1,并将myadd作为参数传入,同时将返回的对象赋值给mydecorator, 可知,这里返回的是log函数,# 也就是说,此时mydecorator指向了log函数print mydecorator(1, 2) # 调用mydecorator函数,即调用内部的log函数
来看一下这段代码的执行结果
C:\Python>python mydecorator1.py3
我们可以看到它的执行结果就是3,你也许会问写了这么多,不就是两个数的求和吗?不就是上面的add函数吗?上面的代码只是便于让大家理解,如果我们在内部的log函数里加一些操作会怎么样呢?比如打印日志。
def add(a, b):return a + bmyadd = adddef minus(a, b):return a - bmyminus = minusdef decorator1(func):def log(*args, **kwargs):# do some things here, for example, add some logprint "function {} was called".format(func.__name__)return func(*args, **kwargs)return logmydecorator1 = decorator1(myadd)mydecorator2 = decorator1(myminus)print mydecorator1(1, 2)print mydecorator2(3, 4)
再来看一下这段代码的执行结果
C:\Python>python mydecorator1.pyfunction add was called3function minus was called-1
我们只需修改内部log函数这一个地方,就可以实现扩充函数的功能,并且这个功能可以应用于多个函数。这就是装饰器最大的意义。这里我是以添加日志为例的,在实际工作中,比如写一个判断是否需要登录操作的装饰器等。
3. python装饰器语法糖
在python的实际工作中,通常使用@符号来调用装饰器,称之为python语法糖。
def decorator1(func):def log(*args, **kwargs):# do some things here, for example, add some logprint "function {} was called".format(func.__name__)return func(*args, **kwargs)return log@decorator1def add(a, b): # 此时 add = decorator1(add),add函数就被装饰了return a + b@decorator1def minus(a, b): # 此时 minus = decorator1(minus),minus函数被装饰了return a - bprint add(1,2) # 执行装饰好的add函数,而不再是原来的add函数print minus(3,4) # 执行装饰好的minus函数,而不再是原来的minus函数
4. 装饰器进阶
上面介绍了基础的装饰器,下面再介绍一些装饰器的进阶用法。
4.1 带参数的装饰器
在上面的例子中,我们可以看到被装饰的函数add,minus是带参数的,但是装饰器decorator1本身除了func这个参数外,是不能带有其他参数的。有没有方法能让装饰器带其他参数呢?比如字符串参数等。答案是可以的,只需要在最外层再封装一个函数即可。
def decorator2(mystring):print mystringdef decorator1(func):def log(*args, **kwargs):# do some things here, for example, add some logprint "function {} was called".format(func.__name__)return func(*args, **kwargs)return logreturn decorator1@decorator2("Used decorator here")def add(a, b):return a + b@decorator2("Used decorator here")def minus(a, b):return a - bprint add(1,2)print minus(3,4)
我们来看这段代码的执行结果
C:\Python>python mydecorator1.pyUsed decorator hereUsed decorator herefunction add was called3function minus was called-1
4.2 多重装饰
截至目前,我们都只使用了一个装饰器,如果适用多个装饰器效果会怎么样呢?
from functools import wrapsdef decorator1(func):@wraps(func)def log(*args, **kwargs):# do some things here, for example, add some logprint "function {} was called in decorator1".format(func.__name__)return func(*args, **kwargs)return logdef decorator2(func):@wraps(func)def another_log(*args, **kwargs):# do some things here, for example, add some logprint "function {} was called in decorator2".format(func.__name__)return func(*args, **kwargs)return another_log@decorator1@decorator2def add(a, b):return a + badd(1, 2)@decorator2@decorator1def minus(a, b):return a - bminus(3, 4)
我们来看这段代码的执行结果
C:\Python>python mydecorator1.pyfunction add was called in decorator1function add was called in decorator2function minus was called in decorator2function minus was called in decorator1
5. 装饰器总结
装饰器是一个接收函数对象,并且返回一个新的函数对象的函数。
装饰器可以在不修改被装饰函数的情况下,实现代码功能的扩充,而不需要重写或者重构代码。
装饰器通常可以用来添加扩充的日志,判断用户某个操作是否需要登录,是否合法等。
装饰器本身也可以带所需的额外参数。
对于多重装饰,装饰的顺序为装饰器的调用顺序。
老司机教你 5 分钟读懂 Python 装饰器相关推荐
- 利用亚运会,读懂 Python装饰器
阅读文本大概需要 5 分钟. 2018 年印度雅加达亚运会已接近尾声,中国在金牌榜和总奖牌榜都遥遥领先于第二名的日本,我也是一名体育爱好者,平时有比赛也会看.看到中国的国旗在海外飘扬,内心会格外的自豪 ...
- 利用世界杯,读懂 Python 装饰器
Python 装饰器是在面试过程高频被问到的问题,装饰器也是一个非常好用的特性, 熟练掌握装饰器会让你的编程思路更加宽广,程序也更加 pythonic. 今天就结合最近的世界杯带大家理解下装饰器. 德 ...
- 利用世界杯,读懂 Python 装饰器 1
Python 装饰器是在面试过程高频被问到的问题,装饰器也是一个非常好用的特性, 熟练掌握装饰器会让你的编程思路更加宽广,程序也更加 pythonic. 今天就结合最近的世界杯带大家理解下装饰器. 德 ...
- 一文读懂Python 装饰器函数
[摘要] Python装饰器的学习笔记 1. 初识装饰器 接下来,我们通过一个例子来为大家讲解这个装饰器: 需求介绍:你现在xx科技有限公司的开发部分任职,领导给你一个业务需求让你完成:让你写代码测试 ...
- 一文读懂 Python 装饰器
Python 是一种对新手很友好的语言.但是,它也有很多较难掌握的高级功能,比如装饰器(decorator).很多初学者一直不理解装饰器及其工作原理,在这篇文章中,我们将介绍装饰器的来龙去脉. 在 P ...
- 面试系列 | 带你彻底搞懂 Python 装饰器
本文作者:Rocky0249 公众号:Python空间 写在之前 「装饰器」作为 Python 高级语言特性中的重要部分,是修改函数的一种超级便捷的方式,适当使用能够有效提高代码的可读性和可维护性,非 ...
- 一文读懂 @Decorator 装饰器——理解 VS Code 源码的基础
作者:easonruan,腾讯 CSIG 前端开发工程师 1. 装饰器的样子 我们先来看看 Decorator 装饰器长什么样子,大家可能没在项目中用过 Decorator 装饰器,但多多少少会看过下 ...
- python内置模块_三分钟读懂Python内置模块collections
collections模块 Python内置模块,在内置数据类型(dict.list.set.tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter.deque.d ...
- python装饰器函数执行后日志_一篇文章搞懂Python装饰器所有用法
如果你接触 Python 有一段时间了的话,想必你对 @ 符号一定不陌生了,没错 @ 符号就是装饰器的语法糖. 它放在一个函数开始定义的地方,它就像一顶帽子一样戴在这个函数的头上.和这个函数绑定在一起 ...
最新文章
- 超赞的贪吃蛇、吃豆人和数字华容道等童年小游戏1行Python代码就能玩
- php中var_dump是什么意思,php中的var_dump()方法的詳細說明
- 学好Python能做什么?有哪些从业方向?
- 剑指OFFER之二进制中1的个数(九度OJ1513)
- mysql 左连接 怎么走索引_mysql left join查询没走索引
- 电脑技巧:键盘上ESC按键的使用小技巧,你都知道吗?
- 【翻译】.NET 5 Preview2发布
- 计算机硬件基础-存取方式
- linux关闭交互模式,linux – 关闭cp(copy)命令的交互模式(cp:overwrite?)
- eclipse aop连接点joinpoint方法点不出来_(面试必备)你必须要懂的Spring-Aop
- cuda Synchronization
- 读取文本作为输出字段
- 快速 二进制,八进制,十进制,十二进制转换 .源码,反码,补码,
- 与复旦大学《数学分析》编者商榷
- ToolStrip工具条
- python便携版本_python便携版安装tk
- 提高文章阅读量的最新技巧
- 【示波器的基本使用】以及【示波器按键面板上各个按键含义的介绍】
- vijos1027-spfa关键路径-休息中的阿呆
- OpenCV 学习第二天
热门文章
- SQL-6查找所有员工入职时候的薪水情况,给出emp_no以及salary, 并按照emp_no进行逆序...
- 使用System.Timers.Timer类实现程序定时执行
- [vijos1162]波浪数
- iOS自定义组与组之间的距离以及视图
- 【51CTO学院三周年】学业有成啦
- Linux学习笔记十三——文件压缩、解压缩和归档
- document.getElementsByName和document.getElementById用法
- nginx+web.py+fastcgi(spawn-fcgi)的session失效問題
- (转载)面试时,你会问面试官哪些问题?
- MyBatis启动流程分析