一 为何要用装饰器

有的时候写完一段代码,过段时间需要对它进行升级、添加一些新功能,但是如果要直接修改原来的代码会影响其他人的调用,所以就需要一个不修改源代码且不修改原函数的调用方式的东西又能为原函数增添新功能的东西,装饰器就是干这个的。

二 什么是装饰器

  1. 装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。
  2. 强调装饰器的原则: 不修改被装饰对象的源代码 不修改被装饰对象的调用方式
  3. 装饰器的目标:在遵循12的前提下,为被装饰对象添加上新功能
  1. 开放封闭原则:对修改封闭,对扩展开放

三 装饰器的使用

下面是为一个函数添加装饰器,添加了计算其运行时间的功能:

  1. import time
  2. def timmer(func):
  3. def wrapper(*args,**kwargs):
  4. start_time=time.time()
  5. res=func(*args,**kwargs)
  6. stop_time=time.time()
  7. print('run time is %s' %(stop_time-start_time))
  8. return res
  9. return wrapper
  10.  
  11. @timmer
  12. def foo():
  13. time.sleep(3)
  14. print('from foo')
  15. foo()

四、装饰器语法及固定格式

  1. def 装饰器函数名(func):
  2. def wrapper(*args,**kwargs):
  3. ret = func(*args,**kwargs)
  4. return ret
  5. return wrapper
  6.  
  7. @装饰器函数名
  8. def func():
  9. pass

五、应用练习

  1. #######################################作业练习#######################################################
  2. #
  3. # 1.编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码
  4. # user_exist = [False]
  5. # def auth(func):
  6. # def wrapper(*args,**kwargs):
  7. # #注册功能
  8. # with open('db.txt','r',encoding='utf-8') as f:
  9. # user_dic = eval(f.read())
  10. # flag = False
  11. # while not user_exist[0]:
  12. # username = input('请输入您的用户名:').strip()
  13. # password = input('请输入您的密码:').strip()
  14. # if username in user_dic and password == user_dic[username]:
  15. # print('恭喜您,登录成功!')
  16. # user_exist[0] = True
  17. # break
  18. # else:
  19. # print('账号或密码错误,请重新输入!')
  20. # ret = func(*args,**kwargs)
  21. # return ret
  22. # return wrapper
  23. #
  24. # @auth
  25. # def func1():
  26. # print('函数1')
  27. # @auth
  28. # def func2(x):
  29. # print('函数2',x)
  30. # func1()
  31. # func2(111111)
  32. # 2.编写装饰器,为多个函数加上记录调用功能,要求每次调用函数都将被调用的函数名称写入文件
  33. # def log(func):
  34. # def wrapper(*args,**kwargs):
  35. # with open('db2.txt','a',encoding='utf-8') as f:
  36. # f.write('%s函数正在被调用。\n'%func.__name__)
  37. # ret = func(*args,**kwargs)
  38. # return ret
  39. # return wrapper
  40. # @log
  41. # def func1():
  42. # print('func1函数被调用了。。。。')
  43. # @log
  44. # def func2():
  45. # print('func2函数被调用了。。。。')
  46. #
  47. # func1()
  48. # func2()
  49. # 进阶作业(选做):
  50. # 1.编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果
  51. from urllib.request import urlopen
  52.  
  53. # def get_html(url):
  54. # print(urlopen(url).read())
  55. #
  56. # get_html('http://www.baidu.com')
  57. # 2.为题目1编写装饰器,实现缓存网页内容的功能:
  58. # 具体:实现下载的页面存放于文件中,如果文件内有值(文件大小不为0),就优先从文件中读取网页内容,否则,就去下载,然后存到文件中
  59. # from urllib.request import urlopen
  60. #
  61. # def get_bak(func):
  62. # def wrapper(*args,**kwargs):
  63. # with open('html.bak','r+',encoding='utf-8') as f:
  64. # if not f.read():
  65. # ret = func(*args, **kwargs)
  66. # print(ret)
  67. # f.write(ret.decode('utf-8'))
  68. # else:
  69. # print('以下内容是从缓存中获得的^^^^^')
  70. # f.seek(0)
  71. # print(f.read())
  72. # ret = func(*args, **kwargs)
  73. # return ret
  74. # return wrapper
  75. #
  76. # @get_bak
  77. # def get_html(url):
  78. # return urlopen(url).read()
  79. # get_html('http://www.python.org')

Python笔记·第十一章—— 函数 (二) 装饰器的更多相关文章

  1. python学习笔记-day4笔记 常用内置函数与装饰器

    1.常用的python函数 abs             求绝对值 all               判断迭代器中所有的数据是否为真或者可迭代数据为空,返回真,否则返回假 any          ...

  2. python 类中的某个函数作为装饰器

    在python的类中,制作一个装饰器的函数, class A: def wrapper(func): ###装饰器 def wrapped(self,*arg,**kwargs) ... return ...

  3. python函数式编程之匿名函数、装饰器、偏函数

    匿名函数 当我们在传入函数时,有些时候,不需要显式的定义函数,直接传入匿名函数就行.如下面 lambda x: x*x 在python中,关键字lambda表示匿名函数,冒号前面的x表示函数参数 匿名 ...

  4. 学习python第十三天,函数5 装饰器decorator

    定义:装饰器本质是函数,(装饰其他函数)就是为其他函数添加附加功能原则:1.不能修改被装饰的函数的源代码 2.不能修改装饰的函数的调用方式 实现装饰器知识储备1函数即变量2.高阶函数,满足2个条件之一 ...

  5. python笔记--3--函数、生成器、装饰器、函数嵌套定义、函数柯里化

    函数 函数定义语法: def 函数名([参数列表]): '''注释''' 函数体 函数形参不需要声明其类型,也不需要指定函数返回值类型 即使该函数不需要接收任何参数,也必须保留一对空的圆括号 括号后面 ...

  6. Python开发基础-Day7-闭包函数和装饰器基础

    补充:全局变量声明及局部变量引用 python引用变量的顺序: 当前作用域局部变量->外层作用域变量->当前模块中的全局变量->python内置变量 global关键字用来在函数或其 ...

  7. python之路 内置函数,装饰器

    一.内置函数 #绝对值 abs() #所有值都为真才为真 all() #只要有一个值为真就为真 any() #10进制转成二进制 bin() #10进制转成八进制 oct() #10进制转成十六进制 ...

  8. Python全栈之路----函数进阶----装饰器

    Python之路,Day4 - Python基础4 (new版) 装饰器 user_status = False #用户登录后改为True def login(func): #传入想调用的函数名 de ...

  9. python基础语法7 闭包函数与装饰器

    闭包函数: 1.闭包函数必须在函数内部定义 2.闭包函数可以引用外层函数的名字 闭包函数是 函数嵌套.函数对象.名称空间与作用域 结合体. # 直接传参 def func(x): print(x) f ...

随机推荐

  1. Chapter 7:Linking

    概述: 在linux上,从c源码到可执行文件主要需要经历translator(compiler.assembler)生成object file,再经由linker连接成executable objec ...

  2. AES高级加密标准简析

    1 AES高级加密标准简介 1.1 概述 高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区 ...

  3. 自学HTML5难 我们应该怎么做

    互联网发展到今天,越来越多的技术岗位人才出现了稀缺的状态,就拿当前的HTML5来讲,基本成为了每家互联网公司不可缺少的人才.如果抓住这个机会,把HTML5搞好,那么前途不可限量,而且这门行业是越老越吃 ...

  4. python/numpy/tensorflow中,对矩阵行列操作,下标是怎么回事儿?

    Python中的list/tuple,numpy中的ndarrray与tensorflow中的tensor. 用python中list/tuple理解,仅仅是从内存角度理解一个序列数据,而非数学中标量 ...

  5. Android 在通知栏实现计时功能

    Notification是APP 向系统发出通知时,它将先以图标的形式显示在通知栏中.用户可以下拉通知栏查看通知的详细信息.我们可以在通知栏实现自定义的效果,也可以结合service和BroadCas ...

  6. A workaround to change shared memory size for Docker containers in AWS ECS

    Issue Because of not supporting to specify the following docker run parameter, containers in ECS can ...

  7. redis复制原理和应用

    1.前言 说到分布式高可用,必然少不了复制,一来是为了做个冗余备份防止数据丢失,二来还可以达到分流来提高性能的目的.基本架构: 下面用M表示Master(主服务器),S表示Slave(从服务器),话不 ...

  8. thinkhphp 上传文件或者图片

  9. win下搭建python3+PyQt5+eric6环境

    一.安装python3 1.下载python3的安装包,默认安装即可,注意勾选 Add Python 3.6 to Path .但是这样默认安装的路径太长,不太方便找到,可选择定制安装,自己定义安装路 ...

  10. 谈谈微服务中的 API 网关(API Gateway)

    前言 又是很久没写博客了,最近一段时间换了新工作,比较忙,所以没有抽出来太多的时间写给关注我的粉丝写一些干货了,就有人问我怎么最近没有更新博客了,在这里给大家抱歉. 那么,在本篇文章中,我们就一起来探 ...