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 + b

myadd = add # myadd引用了这个函数对象

def decorator1(func): # 定义了一个函数对象decorator1,所需参数也是一个函数对象

def log(*args, **kwargs): # 在函数内又定义了一个新的函数对象log

return 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.py

3

我们可以看到它的执行结果就是3,你也许会问写了这么多,不就是两个数的求和吗?不就是上面的add函数吗?上面的代码只是便于让大家理解,如果我们在内部的log函数里加一些操作会怎么样呢?比如打印日志。

def add(a, b):

return a + b

myadd = add

def minus(a, b):

return a - b

myminus = minus

def decorator1(func):

def log(*args, **kwargs):

# do some things here, for example, add some log

print "function {} was called".format(func.__name__)

return func(*args, **kwargs)

return log

mydecorator1 = decorator1(myadd)

mydecorator2 = decorator1(myminus)

print mydecorator1(1, 2)

print mydecorator2(3, 4)

再来看一下这段代码的执行结果

C:\Python>python mydecorator1.py

function add was called

3

function minus was called

-1

我们只需修改内部log函数这一个地方,就可以实现扩充函数的功能,并且这个功能可以应用于多个函数。这就是装饰器最大的意义。这里我是以添加日志为例的,在实际工作中,比如写一个判断是否需要登录操作的装饰器等。

3. python装饰器语法糖

在python的实际工作中,通常使用@符号来调用装饰器,称之为python语法糖。

def decorator1(func):

def log(*args, **kwargs):

# do some things here, for example, add some log

print "function {} was called".format(func.__name__)

return func(*args, **kwargs)

return log

@decorator1

def add(a, b): # 此时 add = decorator1(add),add函数就被装饰了

return a + b

@decorator1

def minus(a, b): # 此时 minus = decorator1(minus),minus函数被装饰了

return a - b

print add(1,2) # 执行装饰好的add函数,而不再是原来的add函数

print minus(3,4) # 执行装饰好的minus函数,而不再是原来的minus函数

4. 装饰器进阶

上面介绍了基础的装饰器,下面再介绍一些装饰器的进阶用法。

4.1 带参数的装饰器

在上面的例子中,我们可以看到被装饰的函数add,minus是带参数的,但是装饰器decorator1本身除了func这个参数外,是不能带有其他参数的。有没有方法能让装饰器带其他参数呢?比如字符串参数等。答案是可以的,只需要在最外层再封装一个函数即可。

def decorator2(mystring):

print mystring

def decorator1(func):

def log(*args, **kwargs):

# do some things here, for example, add some log

print "function {} was called".format(func.__name__)

return func(*args, **kwargs)

return log

return decorator1

@decorator2("Used decorator here")

def add(a, b):

return a + b

@decorator2("Used decorator here")

def minus(a, b):

return a - b

print add(1,2)

print minus(3,4)

我们来看这段代码的执行结果

C:\Python>python mydecorator1.py

Used decorator here

Used decorator here

function add was called

3

function minus was called

-1

4.2 多重装饰

截至目前,我们都只使用了一个装饰器,如果适用多个装饰器效果会怎么样呢?

from functools import wraps

def decorator1(func):

@wraps(func)

def log(*args, **kwargs):

# do some things here, for example, add some log

print "function {} was called in decorator1".format(func.__name__)

return func(*args, **kwargs)

return log

def decorator2(func):

@wraps(func)

def another_log(*args, **kwargs):

# do some things here, for example, add some log

print "function {} was called in decorator2".format(func.__name__)

return func(*args, **kwargs)

return another_log

@decorator1

@decorator2

def add(a, b):

return a + b

add(1, 2)

@decorator2

@decorator1

def minus(a, b):

return a - b

minus(3, 4)

我们来看这段代码的执行结果

C:\Python>python mydecorator1.py

function add was called in decorator1

function add was called in decorator2

function minus was called in decorator2

function minus was called in decorator1

5. 装饰器总结

装饰器是一个接收函数对象,并且返回一个新的函数对象的函数。

装饰器可以在不修改被装饰函数的情况下,实现代码功能的扩充,而不需要重写或者重构代码。

装饰器通常可以用来添加扩充的日志,判断用户某个操作是否需要登录,是否合法等。

装饰器本身也可以带所需的额外参数。

对于多重装饰,装饰的顺序为装饰器的调用顺序。

python重写和装饰器_Python | 老司机教你 5 分钟读懂 Python 装饰器相关推荐

  1. 老司机教你 5 分钟读懂 Python 装饰器

    1. 写在前面 在介绍python装饰器之前,首先介绍python的一个概念,对象.在python里,所有的一切皆对象.常用的python对象有整型对象,浮点型对象,字符串对象,列表对象,元组对象,字 ...

  2. python内置模块_三分钟读懂Python内置模块collections

    collections模块 Python内置模块,在内置数据类型(dict.list.set.tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter.deque.d ...

  3. java和python的web自动化有什么区别-三分钟看懂Python和Java的区别

    随着人工智能的火爆,Python和Java一直在各种流行编程语言中名列前茅.其实Java和Python有些相似,因为很多编程语言之间是互通的.Java现在还是第一,不知道Python未来会不会超越Ja ...

  4. python和java一样吗-三分钟看懂Python和Java的区别

    随着人工智能的火爆,Python和Java一直在各种流行编程语言中名列前茅.其实Java和Python有些相似,因为很多编程语言之间是互通的.Java现在还是第一,不知道Python未来会不会超越Ja ...

  5. python和java的区别-三分钟看懂Python和Java的区别

    随着人工智能的火爆,Python和Java一直在各种流行编程语言中名列前茅.其实Java和Python有些相似,因为很多编程语言之间是互通的.Java现在还是第一,不知道Python未来会不会超越Ja ...

  6. diy计算机组装注意事项,自己组装电脑要注意什么?DIY老司机教你装机注意事项...

    相比品牌机,组装电脑的优势在于个性化的DIY硬件定制,让玩家可以自由选择适合自己的配置,可以说可玩度非常高.如今,电脑硬件设计已经十分人性化,网上还有很多直播教程,用视频的方式直观地教大家装机,不过要 ...

  7. kstools工具是什么牌子_2020年平衡车推荐,电动平衡车哪个牌子好?老司机教你如何选购电动平衡车...

    2020年平衡车推荐,电动平衡车哪个牌子好?老司机教你如何选购电动平衡车 随着我国科技的发展,生活水平的提高,在很多地方都出现了电动平衡车的身影,人们将电动平衡车当做短距离代步的工具,也是非常实用的. ...

  8. java复制屏幕文本内容_网页上的文字内容不给复制?电脑老司机教你输入一串代码,轻松复制...

    原标题:网页上的文字内容不给复制?电脑老司机教你输入一串代码,轻松复制 我们有时候需要一些资料就会去网上查资料,有的时候我们需要把这些资料的文字给复制下来.但并不是所有的资料都能直接复制的,不是登陆账 ...

  9. win10系统升级没有声音?老司机教你怎么重新安装声卡驱动

    win10系统升级没有声音?老司机教你怎么重新安装声卡驱动:http://www.xiaobaixitong.com/win10jiaocheng/29265.html https://www.xit ...

  10. 十年建站老司机带你十分钟搭建网站

    十年建站老司机带你十分钟搭建网站 本文概要: 1. 域名 + 域名注册 + 域名备案 + 域名解析绑定 2. 服务器 + 虚拟主机 + windows服务器 + linux服务器 3. CMS建站系统 ...

最新文章

  1. 题目1195:最长最短文本
  2. AGC005D ~K Perm Counting
  3. 计算机在材料科学中的应用计算机在浓度场中的数值模拟研究,计算机在浓度场中的数值模拟研究.doc...
  4. Keys.js 官方使用说明
  5. 使用VMware虚拟机安装Windows XP系统
  6. 开启MyBatis(三)工作原理
  7. ev加密视频转换成MP4格式,亲测可用
  8. 信息规范和信息安全素养计算机,技师学院计算机专业学生信息安全意识培养的教学研究...
  9. LAMP部署phpadmin
  10. Filename和chunkFilename的区别
  11. python中的除法、取整和求模_python中的除法,取整和求模
  12. 关于win10图标不正常显示的一种解决方法
  13. nginx配置本地静态资源路径
  14. Oracle 宣布 JDK 11 将把 JavaFX 分离成独立模块
  15. 总结归纳“windows 找不到文件‘cmd’,命令提示符无法执行和打开”的多种错误方法规避,错误重现以及正确解决方法
  16. Http请求 RestfulApi请求工具类 RestfulHttpClient
  17. 如何让日志打印更加优雅和实现数据链路追踪?
  18. bing 怎么搜索关键词_Bing更新了网站站长指南,以包含关键字填充
  19. 用python画星座,用python设计程序输生日判断星座,及星座简笔画。
  20. java计算机毕业设计H5新冠防疫宣传网站设计与实现MyBatis+系统+LW文档+源码+调试部署

热门文章

  1. 行为类模式(九):策略(Strategy)
  2. Lync Server 2010迁移至Lync Server 2013部署系列 Part14:A/V服务器目录迁移
  3. ssh公钥的生成、查看以及config的配置
  4. 多服务器消息推送消息,多浏览器窗口接收websocket服务器推送消息问题
  5. python深复制_Python深浅拷贝
  6. JavaWeb开发Servlet学习
  7. android取消自动获取焦点,Android 如何让EditText不自动获取焦点 (转)(示例代码)...
  8. java 财付通支付_微信微信支付已拿下51%的份额,远超支付宝的41%
  9. c++ string split_闲话Python之砍瓜切菜split()
  10. windows中的hosts文件