此系列文档:

1. 我终于弄懂了Python的装饰器(一)

2. 我终于弄懂了Python的装饰器(二)

3. 我终于弄懂了Python的装饰器(三)

4. 我终于弄懂了Python的装饰器(四)

四、装饰器的用法

通用装饰器(这里有一篇文档要补充)

如要制作通用装饰器(无论参数如何,您都可以将其应用于任何函数或方法),则只需使用*args, **kwargs

  1. def a_decorator_passing_arbitrary_arguments(function_to_decorate):
  2. #包装器接受任何参数(这部分可以参考文档:+++++++补充文档+++++++++++++++)
  3. def a_wrapper_accepting_arbitrary_arguments(*args, **kwargs):
  4. print("Do I have args?:")
  5. print(args)
  6. print(kwargs)
  7. function_to_decorate(*args, **kwargs)
  8. return a_wrapper_accepting_arbitrary_arguments
  9. @a_decorator_passing_arbitrary_arguments
  10. def function_with_no_argument():
  11. print("Python is cool, no argument here.")
  12. function_with_no_argument()
  13. #输出:
  14. #Do I have args?:
  15. #()
  16. #{}
  17. #Python is cool, no argument here.
  18. @a_decorator_passing_arbitrary_arguments
  19. def function_with_arguments(a, b, c):
  20. print(a, b, c)
  21. function_with_arguments(1,2,3)
  22. #输出:
  23. #Do I have args?:
  24. #(1, 2, 3)
  25. #{}
  26. #1 2 3
  27. @a_decorator_passing_arbitrary_arguments
  28. def function_with_named_arguments(a, b, c, platypus="Why not ?"):
  29. print("Do {0}, {1} and {2} like platypus? {3}".format(a, b, c, platypus))
  30. function_with_named_arguments("Bill", "Linus", "Steve", platypus="Indeed!")
  31. #输出:
  32. #Do I have args ? :
  33. #('Bill', 'Linus', 'Steve')
  34. #{'platypus': 'Indeed!'}
  35. #Do Bill, Linus and Steve like platypus? Indeed!
  36. class Mary(object):
  37. def __init__(self):
  38. self.age = 31
  39. @a_decorator_passing_arbitrary_arguments
  40. def sayYourAge(self, lie=-3): # You can now add a default value
  41. print("I am {0}, what did you think?".format(self.age + lie))
  42. m = Mary()
  43. m.sayYourAge()
  44. #输出:
  45. # Do I have args?:
  46. #(<__main__.Mary object at 0xb7d303ac>,)
  47. #{}
  48. #I am 28, what did you think?

最佳做法:装饰器

注意:

  • 装饰器是在Python 2.4中引入的,因此请确保您的代码将在> = 2.4上运行。
  • 装饰器使函数调用变慢。(请记住这点)
  • 您不能取消装饰功能。(有一些技巧,可以创建可以被删除的装饰器,但是没有人使用它们。)因此,一旦装饰了一个函数,就对所有代码进行了装饰。
  • 装饰器包装函数,这会使它们难以调试。(这在Python> = 2.5时有所调整;请参见以下内容。)

functools模块是在Python 2.5中引入的。

它包括函数functools.wraps(),该函数将修饰后的函数的名称,模块和文档字符串复制到其包装器中。

(有趣的事是:functools.wraps()也是一个装饰器!)

  1. #为了进行调试,stacktrace将向您显示函数__name__
  2. def foo():
  3. print("foo")
  4. print(foo.__name__)
  5. #输出: foo
  6. #使用装饰器时,输出的信息会变得凌乱,不再是foo,而是wrapper
  7. def bar(func):
  8. def wrapper():
  9. print("bar")
  10. return func()
  11. return wrapper
  12. @bar
  13. def foo():
  14. print("foo")
  15. print(foo.__name__)
  16. #输出: wrapper
  17. # "functools" can help for that
  18. import functools
  19. def bar(func):
  20. # We say that "wrapper", is wrapping "func"
  21. # and the magic begins
  22. @functools.wraps(func)
  23. def wrapper():
  24. print("bar")
  25. return func()
  26. return wrapper
  27. @bar
  28. def foo():
  29. print("foo")
  30. print(foo.__name__)
  31. #outputs: foo

Python本身提供了一些装饰:propertystaticmethod,等。

  • Django使用装饰器来管理缓存和查看权限。
  • 伪造的内联异步函数调用。

如何使用链式装饰器?

  1. # 大胆的使用链式装饰器吧
  2. def makebold(fn):
  3. # The new function the decorator returns
  4. def wrapper():
  5. # Insertion of some code before and after
  6. return "<b>" + fn() + "</b>"
  7. return wrapper
  8. # The decorator to make it italic
  9. def makeitalic(fn):
  10. # The new function the decorator returns
  11. def wrapper():
  12. # Insertion of some code before and after
  13. return "<i>" + fn() + "</i>"
  14. return wrapper
  15. @makebold
  16. @makeitalic
  17. def say():
  18. return "hello"
  19. print(say())
  20. #输出: <b><i>hello</i></b>
  21. # This is the exact equivalent to
  22. def say():
  23. return "hello"
  24. say = makebold(makeitalic(say))
  25. print(say())
  26. #输出: <b><i>hello</i></b>

现在,您可以暂时放下开心的心情,我们来动动脑筋,看看装饰器的高级用法。


原文链接:https://stackoverflow.com/questions/739654/how-to-make-a-chain-of-function-decorators

本文首发于BigYoung小站

我终于弄懂了Python的装饰器(四)的更多相关文章

  1. 我终于弄懂了Python的装饰器(一)

    此系列文档: 1. 我终于弄懂了Python的装饰器(一) 2. 我终于弄懂了Python的装饰器(二) 3. 我终于弄懂了Python的装饰器(三) 4. 我终于弄懂了Python的装饰器(四) 一 ...

  2. 我终于弄懂了Python的装饰器(二)

    此系列文档: 1. 我终于弄懂了Python的装饰器(一) 2. 我终于弄懂了Python的装饰器(二) 3. 我终于弄懂了Python的装饰器(三) 4. 我终于弄懂了Python的装饰器(四) 二 ...

  3. 理解Python中的装饰器//这篇文章将python的装饰器来龙去脉说的很清楚,故转过来存档

    转自:http://www.cnblogs.com/rollenholt/archive/2012/05/02/2479833.html 这篇文章将python的装饰器来龙去脉说的很清楚,故转过来存档 ...

  4. 进阶Python:装饰器 全面详解

    进阶Python:装饰器 前言 前段时间我发了一篇讲解Python调试工具PySnooper的文章,在那篇文章开始一部分我简单的介绍了一下装饰器,文章发出之后有几位同学说"终于了解装饰器的用 ...

  5. Python各式装饰器

    Python装饰器,分两部分,一是装饰器本身的定义,一是被装饰器对象的定义. 一.函数式装饰器:装饰器本身是一个函数. 1.装饰函数:被装饰对象是一个函数 [1]装饰器无参数: a.被装饰对象无参数: ...

  6. Python札记 -- 装饰器补充

    本随笔是对Python札记 -- 装饰器的一些补充. 使用装饰器的时候,被装饰函数的一些属性会丢失,比如如下代码: #!/usr/bin/env python def deco(func): def ...

  7. python基础——装饰器

    python基础——装饰器 由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数. >>> def now(): ... print('2015-3-25 ...

  8. 【转】详解Python的装饰器

    原文链接:http://python.jobbole.com/86717/ Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现 ...

  9. 两个实用的Python的装饰器

    两个实用的Python的装饰器 超时函数 这个函数的作用在于可以给任意可能会hang住的函数添加超时功能,这个功能在编写外部API调用 .网络爬虫.数据库查询的时候特别有用 timeout装饰器的代码 ...

随机推荐

  1. mybatis 学习教程

    https://www.cnblogs.com/ashleyboy/category/1246107.html

  2. 【Spring注解驱动开发】面试官:如何将Service注入到Servlet中?朋友又栽了!!

    写在前面 最近,一位读者出去面试前准备了很久,信心满满的去面试.没想到面试官的一个问题把他难住了.面试官的问题是这样的:如何使用Spring将Service注入到Servlet中呢?这位读者平时也是很 ...

  3. mysql忘记root密码后,重新设置、修改root密码

    大致步骤如下(这个步骤针对5.7版本,8.0之后版本修改方式有所改变,版本为8.0之后的可自行搜索相关修改方法) 1. 关闭正在运行的mysql服务,确保mysql服务要先关闭2. 打开dos窗口,转 ...

  4. css 那些使用小技巧(兼容性)

    1. inline-block 的兼容性问题 display:inline-block; *display:inline; *zoom:1; 2. Microsoft Edge 自动给数字加下划线 在 ...

  5. 8.实战交付一套dubbo微服务到k8s集群(1)之Zookeeper部署

    1.基础架构 主机名 角色 ip HDSS7-11.host.com K8S代理节点1,zk1 10.4.7.11 HDSS7-12.host.com K8S代理节点2,zk2 10.4.7.12 H ...

  6. jmeter在Windows下安装(含插件安装)

    [准备环境] jdk1.8 jmeter的安装包下载 [步骤] 1 把下载下来的压缩包解压,点击jmeter.bat 启动,启动后是英文界面 2 修改默认的英文界面,打开jmeter.properti ...

  7. Error: Cannot find module 'webpack'

    运行 npm start 报错 Error: Cannot find module 'webpack' 安装了 npm install --save-dev webpack cnpm install ...

  8. Python-17-作用域

    python有一个名为vars的内置函数,它返回变量关联的不可见的字典: >>> x = 1  >>> scope = vars()  >>> s ...

  9. 7、struct2的命名空间

    采用命名空间可以区分不同action下面相同的函数名称 我们来看下面的一个程序的代码 我们来看下面的代码: 添加物料的action处理类: package com.weiyuan.test; publ ...

  10. Jenkins入门-环境搭建(1)-转

    因为Jenkins的环境搭建比较简单,本来不想来介绍,但是发现有些入门小朋友,从各种网站上下载的各种安装包来搭建,最后导致出现了各种千奇百怪的问题,介于这种情况下我决定还是来写一下Jenkins的环境 ...