装饰模式有很多经典的使用场景,例如插入日志、性能测试、事务处理等等,有了装饰器,就可以提取大量函数中与本身功能无关的类似代码,从而达到代码重用的目的。下面就一步步看看Python中的装饰器。

一个简单的需求

现在有一个简单的函数”myfunc”,想通过代码得到这个函数的大概执行时间。

我们可以直接把计时逻辑方法”myfunc”内部,但是这样的话,如果要给另一个函数计时,就需要重复计时的逻辑。所以比较好的做法是把计时逻辑放到另一个函数中(”deco”),如下:

但是,上面的做法也有一个问题,就是所有的”myfunc”调用处都要改为”deco(myfunc)”。

下面,做一些改动,来避免计时功能对”myfunc”函数调用代码的影响:

经过了上面的改动后,一个比较完整的装饰器(deco)就实现了,装饰器没有影响原来的函数,以及函数调用的代码。例子中值得注意的地方是,Python中一切都是对象,函数也是,所以代码中改变了”myfunc”对应的函数对象。

装饰器语法糖

在Python中,可以使用”@”语法糖来精简装饰器的代码:

使用了”@”语法糖后,我们就不需要额外代码来给”myfunc”重新赋值了,其实”@deco”的本质就是”myfunc = deco(myfunc)”,当认清了这一点后,后面看带参数的装饰器就简单了。

被装饰的函数带参数

前面的例子中,被装饰函数的本身是没有参数的,下面看一个被装饰函数有参数的例子:

从例子中可以看到,对于被装饰函数需要支持参数的情况,我们只要使装饰器的内嵌函数支持同样的签名即可。

也就是说这时,”addFunc(3, 8) = deco(addFunc(3, 8))”。

这里还有一个问题,如果多个函数拥有不同的参数形式,怎么共用同样的装饰器?在Python中,函数可以支持(*args, **kwargs)可变参数,所以装饰器可以通过可变参数形式来实现内嵌函数的签名。

带参数的装饰器

装饰器本身也可以支持参数,例如说可以通过装饰器的参数来禁止计时功能:

通过例子可以看到,如果装饰器本身需要支持参数,那么装饰器就需要多一层的内嵌函数。

这时候,”addFunc(3, 8) = deco(True)( addFunc(3, 8))”,”myFunc() = deco(False)( myFunc ())”。

装饰器调用顺序

装饰器是可以叠加使用的,那么这是就涉及到装饰器调用顺序了。对于Python中的”@”语法糖,装饰器的调用顺序与使用 @ 语法糖声明的顺序相反。

在这个例子中,”addFunc(3, 8) = deco_1(deco_2(addFunc(3, 8)))”。

Python内置装饰器

在Python中有三个内置的装饰器,都是跟class相关的:staticmethod、classmethod 和property。

  • staticmethod 是类静态方法,其跟成员方法的区别是没有 self 参数,并且可以在类不进行实例化的情况下调用
  • classmethod 与成员方法的区别在于所接收的第一个参数不是 self (类实例的指针),而是cls(当前类的具体类型)
  • property 是属性的意思,表示可以通过通过类实例直接访问的信息

对于staticmethod和classmethod这里就不介绍了,通过一个例子看看property。

注意,对于Python新式类(new-style class),如果将上面的 “@var.setter” 装饰器所装饰的成员函数去掉,则Foo.var 属性为只读属性,使用 “foo.var = ‘var 2′” 进行赋值时会抛出异常。但是,对于Python classic class,所声明的属性不是 read-only的,所以即使去掉”@var.setter”装饰器也不会报错。

总结

本文介绍了Python装饰器的一些使用,装饰器的代码还是比较容易理解的。只要通过一些例子进行实际操作一下,就很容易理解了。

转自:http://www.cnblogs.com/wilber2013/p/4657155.html

python装饰器2的更多相关文章

  1. 关于python装饰器

    关于python装饰器,不是系统的介绍,只是说一下某些问题 1 首先了解变量作用于非常重要 2 其次要了解闭包 def logger(func): def inner(*args, **kwargs) ...

  2. python装饰器通俗易懂的解释!

    1.python装饰器 刚刚接触python的装饰器,简直懵逼了,直接不懂什么意思啊有木有,自己都忘了走了多少遍Debug,查了多少遍资料,猜有点点开始明白了.总结了一下解释得比较好的,通俗易懂的来说 ...

  3. Python 装饰器学习

    Python装饰器学习(九步入门)   这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 1 2 3 4 5 6 7 8 # -*- c ...

  4. python 装饰器修改调整函数参数

    简单记录一下利用python装饰器来调整函数的方法.现在有个需求:参数line范围为1-16,要求把9-16的范围转化为1-8,即9对应1,10对应2,...,16对应8. 下面是例子: def fo ...

  5. python 装饰器学习(decorator)

    最近看到有个装饰器的例子,没看懂, #!/usr/bin/python class decorator(object): def __init__(self,f): print "initi ...

  6. Python装饰器详解

    python中的装饰器是一个用得非常多的东西,我们可以把一些特定的方法.通用的方法写成一个个装饰器,这就为调用这些方法提供一个非常大的便利,如此提高我们代码的可读性以及简洁性,以及可扩展性. 在学习p ...

  7. 关于python装饰器(Decorators)最底层理解的一句话

    一个decorator只是一个带有一个函数作为参数并返回一个替换函数的闭包. http://www.xxx.com/html/2016/pythonhexinbiancheng_0718/1044.h ...

  8. Python装饰器由浅入深

    装饰器的功能在很多语言中都有,名字也不尽相同,其实它体现的是一种设计模式,强调的是开放封闭原则,更多的用于后期功能升级而不是编写新的代码.装饰器不光能装饰函数,也能装饰其他的对象,比如类,但通常,我们 ...

  9. Python装饰器与面向切面编程

    今天来讨论一下装饰器.装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数 ...

  10. python装饰器方法

    前几天向几位新同事介绍项目,被问起了@login_required的实现,我说这是django框架提供的装饰器方法,验证用户是否登录,只要这样用就行了,因为自己不熟,并没有做过多解释. 今天查看dja ...

随机推荐

  1. windows 服务下搭建jsp运行环境

    此处搭建的是运行环境,不是开发环境. 1, 下载sdk 并安装  1.8      http://rj.baidu.com/soft/detail/14459.html?ald 2, 配置环境变量 步 ...

  2. 玩转xargs

    xargs命令可以把标准输入数据转换成命令行参数.也可以将单行或多行文本输入转换成其他格式,是构建单行命令的重要组件之一. xargs命令应该紧跟在管道操作符之后,以stdin作为主要的源数据流,使用 ...

  3. spring cloud深入学习(八)-----配置中心svn示例和refresh

    svn版本 同样先示例server端的代码,基本步骤一样. 1.添加依赖 <dependencies> <dependency> <groupId>org.spri ...

  4. Python字符串切片操作知识详解

    Python字符串切片操作知识详解 这篇文章主要介绍了Python中字符串切片操作 的相关资料,需要的朋友可以参考下 一:取字符串中第几个字符 print "Hello"[0] 表 ...

  5. 【DM642学习笔记三】flash的烧写

    ICETEK-DM642-PCI板上的29L008B芯片提供了8M位的Flash空间(访问地址空间是CE1,90000000h~90080000h).主要用于自启动功能和存储FPGA的配置数据. 一. ...

  6. 忘记sql server 2008 sa的密码的解决方案

      解决的办法的前提是:可以混合模式登陆1.用windows身份验证登陆.2.新建查询3.输入 EXEC sp_password NULL, 'newPassword', sa搞定了

  7. 2019-8-30-BAT-脚本判断当前系统是-x86-还是-x64-系统

    title author date CreateTime categories BAT 脚本判断当前系统是 x86 还是 x64 系统 lindexi 2019-08-30 08:47:40 +080 ...

  8. Luogu P1712 [NOI2016]区间(线段树)

    P1712 [NOI2016]区间 题意 题目描述 在数轴上有 \(N\) 个闭区间 \([l_1,r_1],[l_2,r_2],...,[l_n,r_n]\) .现在要从中选出 \(M\) 个区间, ...

  9. 更好用的集群限流功能,Sentinel 发布 v1.4.2

    摘要: 感谢 Sentinel 社区的贡献者们 ️ Sentinel 发布 v1.4.2 正式发布,该版本主要变更如下: 特性/功能改进 新增 Zuul 1.x 适配模块(sentinel-zuul- ...

  10. [Array]448. Find All Numbers Disappeared in an Array

    Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and ot ...