什么是装饰器

器即函数

装饰即修饰,意指为其他函数添加新功能

装饰器定义:本质就是函数,功能是为其他函数添加新功能

装饰器需要遵循的原则

1.不修改被装饰函数的源代码(开放封闭原则)

2.为被装饰函数添加新功能后,不修改被修饰函数的调用方式

实现装饰器知识储备

装饰器=高阶函数+函数嵌套+闭包

高阶函数

高阶函数定义:
1.函数接收的参数是一个函数名

2.函数的返回值是一个函数名

3.满足上述条件任意一个,都可称之为高阶函数

  1. def foo():
  2. print('我的函数名作为参数传给高阶函数')
  3. def gao_jie1(func):
  4. print('我就是高阶函数1,我接收的参数名是%s' %func)
  5. func()
  6.  
  7. def gao_jie2(func):
  8. print('我就是高阶函数2,我的返回值是%s' %func)
  9. return func
  10.  
  11. gao_jie1(foo)
  12. gao_jie2(foo)

高阶函数示范

  1. #高阶函数应用1:把函数当做参数传给高阶函数
  2. import time
  3. def foo():
  4. print('from the foo')
  5.  
  6. def timmer(func):
  7. start_time=time.time()
  8. func()
  9. stop_time=time.time()
  10. print('函数%s 运行时间是%s' %(func,stop_time-start_time))
  11. timmer(foo)
  12. #总结:我们确实为函数foo增加了foo运行时间的功能,但是foo原来的执行方式是foo(),现在我们需要调用高阶函数timmer(foo),改变了函数的调用方式

把函数当做参数传给高阶函数

  1. #高阶函数应用2:把函数名当做参数传给高阶函数,高阶函数直接返回函数名
  2. import time
  3. def foo():
  4. print('from the foo')
  5.  
  6. def timmer(func):
  7. start_time=time.time()
  8. return func
  9. stop_time=time.time()
  10. print('函数%s 运行时间是%s' %(func,stop_time-start_time))
  11. foo=timmer(foo)
  12. foo()
  13. #总结:我们确实没有改变foo的调用方式,但是我们也没有为foo增加任何新功能

函数返回值是函数名

高阶函数总结
1.函数接收的参数是一个函数名
  作用:在不修改函数源代码的前提下,为函数添加新功能,
  不足:会改变函数的调用方式
2.函数的返回值是一个函数名
  作用:不修改函数的调用方式
  不足:不能添加新功能

函数嵌套

  1. def father(name):
  2. print('from father %s' %name)
  3. def son():
  4. print('from son')
  5. def grandson():
  6. print('from grandson')
  7. grandson()
  8. son()
  9.  
  10. father('康明')

闭包

  1. '''
  2. 闭包:在一个作用域里放入定义变量,相当于打了一个包
  3. '''
  4. def father(name):
  5. def son():
  6. # name='alex'
  7. print('我爸爸是 [%s]' %name)
  8. def grandson():
  9. # name='wupeiqi'
  10. print('我爷爷是 [%s]' %name)
  11. grandson()
  12. son()
  13.  
  14. father('康明')

无参装饰器

无参装饰器=高级函数+函数嵌套

基本框架

  1. #这就是一个实现一个装饰器最基本的架子
  2. def timer(func):
  3. def wrapper():
  4. func()
  5. return wrapper

加上参数

  1. def timer(func):
  2. def wrapper(*args,**kwargs):
  3. func(*args,**kwargs)
  4. return wrapper

加上功能

  1. import time
  2. def timer(func):
  3. def wrapper(*args,**kwargs):
  4. start_time=time.time()
  5. func(*args,**kwargs)
  6. stop_time=time.time()
  7. print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time))
  8. return wrapper

加上返回值

  1. import time
  2. def timer(func):
  3. def wrapper(*args,**kwargs):
  4. start_time=time.time()
  5. res=func(*args,**kwargs)
  6. stop_time=time.time()
  7. print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time))
  8. return res
  9. return wrapper

使用装饰器

  1. def cal(array):
  2. res=0
  3. for i in array:
  4. res+=i
  5. return res
  6.  
  7. cal=timer(cal)
  8. cal(range(10))

语法糖@

  1. @timer #@timer就等同于cal=timer(cal)
  2. def cal(array):
  3. res=0
  4. for i in array:
  5. res+=i
  6. return res
  7.  
  8. cal(range(10))

装饰器应用示例

  1. user_list=[
  2. {'name':'alex','passwd':''},
  3. {'name':'linhaifeng','passwd':''},
  4. {'name':'wupeiqi','passwd':''},
  5. {'name':'yuanhao','passwd':''},
  6. ]
  7.  
  8. current_user={'username':None,'login':False}
  9.  
  10. def auth_deco(func):
  11. def wrapper(*args,**kwargs):
  12. if current_user['username'] and current_user['login']:
  13. res=func(*args,**kwargs)
  14. return res
  15. username=input('用户名: ').strip()
  16. passwd=input('密码: ').strip()
  17.  
  18. for index,user_dic in enumerate(user_list):
  19. if username == user_dic['name'] and passwd == user_dic['passwd']:
  20. current_user['username']=username
  21.  
  22. current_user['login']=True
  23. res=func(*args,**kwargs)
  24. return res
  25. break
  26. else:
  27. print('用户名或者密码错误,重新登录')
  28.  
  29. return wrapper
  30.  
  31. @auth_deco
  32. def index():
  33. print('欢迎来到主页面')
  34.  
  35. @auth_deco
  36. def home():
  37. print('这里是你家')
  38.  
  39. def shopping_car():
  40. print('查看购物车啊亲')
  41.  
  42. def order():
  43. print('查看订单啊亲')
  44.  
  45. print(user_list)
  46. # index()
  47. print(user_list)
  48. home()

无参装饰器

  1. user_list=[
  2. {'name':'alex','passwd':''},
  3. {'name':'linhaifeng','passwd':''},
  4. {'name':'wupeiqi','passwd':''},
  5. {'name':'yuanhao','passwd':''},
  6. ]
  7.  
  8. current_user={'username':None,'login':False}
  9. def auth(auth_type='file'):
  10. def auth_deco(func):
  11. def wrapper(*args,**kwargs):
  12. if auth_type == 'file':
  13. if current_user['username'] and current_user['login']:
  14. res=func(*args,**kwargs)
  15. return res
  16. username=input('用户名: ').strip()
  17. passwd=input('密码: ').strip()
  18.  
  19. for index,user_dic in enumerate(user_list):
  20. if username == user_dic['name'] and passwd == user_dic['passwd']:
  21. current_user['username']=username
  22. current_user['login']=True
  23. res=func(*args,**kwargs)
  24. return res
  25. break
  26. else:
  27. print('用户名或者密码错误,重新登录')
  28. elif auth_type == 'ldap':
  29. print('巴拉巴拉小魔仙')
  30. res=func(*args,**kwargs)
  31. return res
  32. return wrapper
  33. return auth_deco
  34.  
  35. #auth(auth_type='file')就是在运行一个函数,然后返回auth_deco,所以@auth(auth_type='file')
  36. #就相当于@auth_deco,只不过现在,我们的auth_deco作为一个闭包的应用,外层的包auth给它留了一个auth_type='file'参数
  37. @auth(auth_type='ldap')
  38. def index():
  39. print('欢迎来到主页面')
  40.  
  41. @auth(auth_type='ldap')
  42. def home():
  43. print('这里是你家')
  44.  
  45. def shopping_car():
  46. print('查看购物车啊亲')
  47.  
  48. def order():
  49. print('查看订单啊亲')
  50.  
  51. # print(user_list)
  52. index()
  53. # print(user_list)
  54. home()

带参装饰器

超时装饰器

  1. import sys,threading,time
  2.  
  3. class KThread(threading.Thread):
  4.  
  5. """A subclass of threading.Thread, with a kill()
  6.  
  7. method.
  8.  
  9. Come from:
  10.  
  11. Kill a thread in Python:
  12.  
  13. http://mail.python.org/pipermail/python-list/2004-May/260937.html
  14.  
  15. """
  16.  
  17. def __init__(self, *args, **kwargs):
  18.  
  19. threading.Thread.__init__(self, *args, **kwargs)
  20.  
  21. self.killed = False
  22.  
  23. def start(self):
  24.  
  25. """Start the thread."""
  26.  
  27. self.__run_backup = self.run
  28.  
  29. self.run = self.__run # Force the Thread to install our trace.
  30.  
  31. threading.Thread.start(self)
  32.  
  33. def __run(self):
  34.  
  35. """Hacked run function, which installs the
  36.  
  37. trace."""
  38.  
  39. sys.settrace(self.globaltrace)
  40.  
  41. self.__run_backup()
  42.  
  43. self.run = self.__run_backup
  44.  
  45. def globaltrace(self, frame, why, arg):
  46.  
  47. if why == 'call':
  48.  
  49. return self.localtrace
  50.  
  51. else:
  52.  
  53. return None
  54.  
  55. def localtrace(self, frame, why, arg):
  56.  
  57. if self.killed:
  58.  
  59. if why == 'line':
  60.  
  61. raise SystemExit()
  62.  
  63. return self.localtrace
  64.  
  65. def kill(self):
  66.  
  67. self.killed = True
  68.  
  69. class Timeout(Exception):
  70.  
  71. """function run timeout"""
  72.  
  73. def timeout(seconds):
  74.  
  75. """超时装饰器,指定超时时间
  76.  
  77. 若被装饰的方法在指定的时间内未返回,则抛出Timeout异常"""
  78.  
  79. def timeout_decorator(func):
  80.  
  81. """真正的装饰器"""
  82.  
  83. def _new_func(oldfunc, result, oldfunc_args, oldfunc_kwargs):
  84.  
  85. result.append(oldfunc(*oldfunc_args, **oldfunc_kwargs))
  86.  
  87. def _(*args, **kwargs):
  88.  
  89. result = []
  90.  
  91. new_kwargs = { # create new args for _new_func, because we want to get the func return val to result list
  92.  
  93. 'oldfunc': func,
  94.  
  95. 'result': result,
  96.  
  97. 'oldfunc_args': args,
  98.  
  99. 'oldfunc_kwargs': kwargs
  100.  
  101. }
  102.  
  103. thd = KThread(target=_new_func, args=(), kwargs=new_kwargs)
  104.  
  105. thd.start()
  106.  
  107. thd.join(seconds)
  108.  
  109. alive = thd.isAlive()
  110.  
  111. thd.kill() # kill the child thread
  112.  
  113. if alive:
  114.  
  115. raise Timeout(u'function run too long, timeout %d seconds.' % seconds)
  116.  
  117. else:
  118.  
  119. return result[0]
  120.  
  121. _.__name__ = func.__name__
  122.  
  123. _.__doc__ = func.__doc__
  124.  
  125. return _
  126.  
  127. return timeout_decorator
  128.  
  129. @timeout(5)
  130.  
  131. def method_timeout(seconds, text):
  132.  
  133. print('start', seconds, text)
  134.  
  135. time.sleep(seconds)
  136.  
  137. print('finish', seconds, text)
  138.  
  139. return seconds
  140.  
  141. method_timeout(6,'asdfasdfasdfas')

python学习---装饰器的更多相关文章

  1. Python学习---装饰器/迭代器/生成器的学习【all】

    Python学习---装饰器的学习1210 Python学习---生成器的学习1210 Python学习---迭代器学习1210

  2. Python学习---装饰器的学习1210

    装饰器的基础 学习前提: 作用域 + 函数的理解 + 闭包  [学习,理解] 代码编写原则: 对修改开放对扩展开放 装饰器本质上是一个函数,该函数用来处理其他函数,它可以让其他函数在不需要修改代码的前 ...

  3. python学习——装饰器函数

    一.装饰器函数的作用是什么 答:装饰器函数是在不修改原函数及其调用方式的情况下对原函数功能进行扩展 对于搞python开发的人来说,函数占据了至关重要的地位.都说学好函数你就可以去找工作了,好了,假如 ...

  4. Python学习——装饰器/decorator/语法糖

    装饰器 定义:本质是函数,为其他函数添加附加的功能. 原则:1.不能修改原函数的源代码 2.不能修改被原函数的调用方式 重点理解: 1.函数即“变量” 2.高阶函数:返回值中包含函数名 3.嵌套函数 ...

  5. day12 python学习 装饰器

    闭包函数: 内部函数包含对外部作用域而非全剧作用域名字的引用,该内部函数称为闭包函数#函数内部定义的函数称为内部函数 闭包函数获取网络应用 from urllib.request import url ...

  6. python之循序渐进学习装饰器

    python装饰器的定义:在代码运行期间在不改变原函数定义的基础上,动态给该函数增加功能的方式称之为装饰器(Decorator) 装饰器的优点和用途: 1. 抽离出大量函数中与函数功能本身无关的的雷同 ...

  7. python基础 (装饰器,内置函数)

    https://docs.python.org/zh-cn/3.7/library/functions.html 1.闭包回顾 在学习装饰器之前,可以先复习一下什么是闭包? 在嵌套函数内部的函数可以使 ...

  8. python初级装饰器编写

    最近项目太忙好久没有学习python了,今天更新一下吧~~ 1.什么是python装饰器: 装饰器本质上是一个python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外的功能,装饰器的返 ...

  9. Python之装饰器、迭代器和生成器

    在学习python的时候,三大“名器”对没有其他语言编程经验的人来说,应该算是一个小难点,本次博客就博主自己对装饰器.迭代器和生成器理解进行解释. 为什么要使用装饰器 什么是装饰器?“装饰”从字面意思 ...

随机推荐

  1. Html5 Page Creator,简易h5页面场景制作

  2. opencv学习之路(35)、SURF特征点提取与匹配(三)

    一.简介 二.opencv中的SURF算法接口 三.特征点匹配方法 四.代码 1.特征点提取 #include "opencv2/opencv.hpp" #include < ...

  3. vs2013突然打不开项目,项目全部不兼容

    转载:https://forum.cocos.com/t/vs2013/40931 转载:https://jingyan.baidu.com/article/cdddd41c7c6b5353cb00e ...

  4. 20175312 2018-2019-2 实验一《Java开发环境的熟悉》实验报告

    20175312 2018-2019-2 实验一<Java开发环境的熟悉>实验报告 实验内容 1.使用JDK编译.运行简单的Java程序: 2.使用Eclipse 编辑.编译.运行.调试J ...

  5. kamailio 云部署 配置NAT

    公有云配置NAT 第一步:将内网ip广播至公网ip,编辑/etc/kamailio/kamailio.cfg文件,搜索listen,添加如下配置 # listen=udp: listen= adver ...

  6. #!/usr/bin/python3 和 #!/usr/bin/env python3的区别

    脚本语言的第一行指出用什么程序去执行代码. #!/usr/bin/python3调用/usr/bin下的python3解释器.#!/usr/bin/env python3首先会到env设置里查找pyt ...

  7. threejs深入纹理,立体场景cubeResolution(四)

    在这个课程里主要完成讲解两个demo: 一个是电视墙:用视频做纹理 一,用视频做纹理 首先我们用video标签把视频源引入: <video id="video" autopl ...

  8. mybatis-generator 自动生成mapper以及实体类

    研究了一下,感觉也不是特别方便,因为参数很多都是需要手动去配置的,如果在这个jar基础上在改造一下或许更方便一点. 具体实现代码如下: pom.xml <plugin> <group ...

  9. 雷林鹏分享:url中加号引发的错误

    刚发现了博客的一个bug,标签页中一些标签带有空格,在url输出中使用了 urlencode 函数进行处理,导致空格被转换成了加号(+),这时通过url访问时会出现错误: 临时解决方法是在urlcod ...

  10. eee

    package demo; public class Phone { String phonexinghao; String phonepinpai; public void shouji (){ S ...