date: 2017-04-14 00:06:46

Python的装饰器,顾名思义就是可以为已有的函数或对象起到装饰的作用,使得达到代码重用的目的。

从一个简单的例子出发

这个例子中我们已经拥有了若干个独立的函数。

#! python 2
# coding: utf-8def a():print("a")def b():print("b")def c():print("c")a()
b()
c()

输出结果是

a
b
c

而我们想要给这三个函数都加上打印当前日期的功能,倘若没有学习装饰器,那我们可能要为每一个函数都添加一行语句。

#! python 2
# coding: utf-8import timedef a():print(time.asctime( time.localtime(time.time())))print("a")def b():print(time.asctime( time.localtime(time.time())))print("b")def c():print(time.asctime( time.localtime(time.time())))print("c")a()
b()
c()

这样看来需要添加的代码量似乎并不多,但如果需要被添加此功能的已经写好的模块已经有上百上千甚至上万?这样写岂不是过于繁杂,而有了装饰器,我们则可以像下面这样。

#! python3
# coding: utf-8import time# return time
def rtime(func):def wrapper():print(time.asctime( time.localtime(time.time())))return func()return wrapper@rtime
def a():print("a")@rtime
def b():print("b")@rtime
def c():print("c")a()
b()
c()

怎么样,是不是简洁明了了很多。

更加通用一点的装饰器

可以看到,上面的三个函数都没有接受参数,那如果rtime去装饰含有参数的函数会怎样呢?

#! python3
# coding: utf-8import time# return time
def rtime(func):def wrapper():print(time.asctime(time.localtime(time.time())))return func()return wrapper@rtime
def d(a):print(a)d(1)

显然,d函数包含了一个参数d,如果此时运行的话,则会出现报错

TypeError: wrapper() takes no arguments (1 given)

为了可以使得装饰器更加通用,我们可以像下面这样写:

#! python3
# coding: utf-8import time# return time
def rtime(func):def wrapper(*args, **kwargs):print(time.asctime(time.localtime(time.time())))return func(*args, **kwargs)return wrapper@rtime
def d(a):print(a)d(1)

可以看到,其中添加了*args和**kwargs,Python提供了可变参数*args和关键字参数**kwargs用于处理未知数量参数,这样就能解决被修饰函数中带参数得问题。

那如果是装饰器本身想要带上参数呢,先记住这样一句话:本身需要支持参数得装饰器需要多一层的内嵌函数。下面看具体的代码实现:

#! python3
# coding: utf-8import time# return time
def rtime(x):print(x)def wrapper(func):def inner_wrapper(*args, **kwargs):print(time.asctime(time.localtime(time.time())))return func(*args, **kwargs)return inner_wrapperreturn wrapper@rtime(1) # x = 1
def d(a):print(a)d(2)

输出结果为

1
Wed Apr 12 20:43:54 2017
2

调用多个装饰器

python的装饰器支持多次调用,且调用的顺序与在被装饰函数前声明装饰器的顺序相反,如若想先调用装饰器demo1和demo2,则装饰时应先@demo2再@demo1。

类实现的装饰器

若想要通过类来实现装饰器,则需要修改类的构造函数__init__()并重载__call__()函数。下面是一个简单的例子:

#! python3
# coding: utf-8import time# return time
def rtime(x):print(x)def wrapper(func):def inner_wrapper(*args, **kwargs):print(time.asctime(time.localtime(time.time())))return func(*args, **kwargs)return inner_wrapperreturn wrapper# return time 不带参数的类实现
class rtime1(object):def __init__(self, func):self.func = funcdef __call__(self, *args, **kwargs):print(time.asctime(time.localtime(time.time())))return self.func(*args, **kwargs)# return time 带参数的类实现
class rtime2(object):def __init__(self, x):self.x = xdef __call__(self, func):def wrapper(*args, **kwargs):print(self.x)print(time.asctime(time.localtime(time.time())))return func(*args, **kwargs)return wrapper@rtime(1)
def d(a):print(a)@rtime1
def e(a):print(a)@rtime2(2)
def f(a):print(a)d(3)
e(4)
f(5)

输出结果为

1
Thu Apr 13 11:32:22 2017
3
Thu Apr 13 11:32:22 2017
4
2
Thu Apr 13 11:32:22 2017
5

Python内置装饰器

@property

内置装饰器property可以帮助我们为一个class写入属性

#! python3
# coding: utf-8import timeclass test(object):@propertydef x(self):return self._x@x.setterdef x(self, value):self._x = value@x.deleterdef x(self):del self._xtemp = test()
temp.x = 1
print temp.x

输出结果为1,想必会有人疑惑为什么要这样写入属性,如果没有这样绑定属性直接将temp.x赋值的话,则属性x是不可控的,而通过property绑定属性之后,则可以在setter设定的时候添加对范围的判断,使得属性可控,property还有getter装饰器,不过getter装饰器和不带getter的属性装饰器效果一样。

@staticmethod & @classmethod

通过staticmethod和classmethod装饰器可以使得我们在不实例化类的情况下直接调用类中的方法:class_name.method()即可直接调用。

那么staticmethod和classmethod又有什么区别呢?

@staticmethod不需要表示实例的self和自身类的cls参数,也就是说可不传递参数。

@classmethod的第一个参数必须有且必须是表示自身类的cls参数。

转载于:https://www.cnblogs.com/Mu001999/p/8134249.html

理解Python装饰器(Decorator)相关推荐

  1. python装饰器-理解Python装饰器(Decorator)

    理解Python装饰器(Decorator) Python装饰器看起来类似Java中的注解,然鹅和注解并不相同,不过同样能够实现面向切面编程. 想要理解Python中的装饰器,不得不先理解闭包(clo ...

  2. python lock_python lock一步步教你理解Python装饰器

    请仔细看我们的decorator实例.我们定义了一个接受单个参数some_func的名为outer的函数.在outer内部我们定义了一个名为inner的嵌套函数.inner函数打印一个字符串然后调用s ...

  3. python装饰器由浅入深_由浅入深理解Python装饰器

    前提知识: 1.Python里函数也是一种对象: def shout(word="yes"): return word.capitalize()+"!" pri ...

  4. python装饰器理解_如何理解Python装饰器?

    首先,本垃圾文档工程师又来了.开始日常的水文写作.起因是看到这个问题如何理解Python装饰器?,正好不久前给人讲过这些,本垃圾于是又开始新的一轮辣鸡文章写作行为了. 预备知识 首先要理解装饰器,首先 ...

  5. 如何理解python装饰器

    如何理解python装饰器 @(Python学习-随手记)[Decorator, 帮助] 装饰器简介 装饰器decorator是一种高级python语法,可以对函数.方法.类进行加工. 装饰器常用场景 ...

  6. python装饰器(Decorator)【修改】

    python装饰器(Decorator) python装饰器(Decorator) python装饰器(decorator)官方定义 [https://docs.python.org/zh-cn/3/ ...

  7. python装饰器原理-深刻理解python装饰器

    我们要完全理解python装饰器,不是很容易,主要归结有如下困难: 1. 关于函数"变量"(或"变量"函数)的理解 2. 关于高阶函数的理解 3. 关于嵌套函数 ...

  8. Get技能---Python 装饰器Decorator

    Get技能---Python 装饰器Decorator Python装饰器 装饰器概述 从需求引入装饰器 监控一段代码执行时间,最原始的实现 监控一段代码执行时间,以函数传参的形式实现 监控一段代码执 ...

  9. 理解TS装饰器Decorator

    理解TS装饰器Decorator 介绍 类装饰器 方法装饰器 介绍 详细的关于ts中装饰器的使用和语法可以参考 ts官网中decorator这一章节,或者阮一峰的ts教程的decorator章节这里这 ...

  10. 如何理解Python装饰器?

    Python 装饰器使用非常地简单.任何会使用 Python 函数的人都可以学习使用装饰器: Python 1 2 3 @somedecorator def some_function():      ...

最新文章

  1. Load和Initialize往死了问是一种怎样的体验?
  2. 2019年IT人加薪的9大神器
  3. java ee中javamail注解_JavaEE之注解
  4. mongodb小结(转)
  5. java实现插入排序算法 附单元测试源码
  6. 软件测试工程师-开发与测试模型
  7. Linux系统Bash的常用功能(9)
  8. 恶意软件借手机游戏强行吸取流量,使用代码签名证书验明证身
  9. MySQL 8.0设置sort_buffer_size
  10. 计算机用三角函数时如何用弧度制,5.1.2弧度制教学设计
  11. 学习参考《深度实践Spark机器学习》PDF+吴茂贵
  12. Rainmeter天气不能更新、win地图不能检测定位
  13. 曾在国内外5家大厂做数据库工程师,这是他给出的5大数据库趋势预测
  14. Spread控件使用说明_技术部分
  15. 布同:3D网游开发整体流程简述
  16. java set方法无法使用_Java setBounds无法与JPanel一起使用
  17. BouncyCastle库
  18. C语言程序设计ncre,NCRE二级C语言程序设计辅导
  19. ant design vue中a-table中使用a-tag和a-switch
  20. 蓝代斯克和玖道在华设立合资企业

热门文章

  1. php简单多态,PHP 对象 多态性 简单图形计算器
  2. vscode markdown实时预览
  3. idea中resources下的logback-spring的配置
  4. linux进程睡眠的介绍
  5. JDK1.8源码(十一)——java.util.TreeMap类
  6. python题目训练(随时更新)
  7. 【转】如何有效地记忆与学习
  8. (转)10条名言,让你少走弯路
  9. Web前后端缓存技术(缓存的主要作用是什么)
  10. 当spark遇见hbase