装饰器

装饰器本质上就是一个python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离大量与函数功能本身无关的雷同代码并继续重用。概括讲,装饰器的作用就是为依据存在的对象添加额外的功能。

定义:本质是函数,(装饰其他函数)就是为其他函数添加附加功能
原则:
  • 不能修改被装饰的函数的源代码( 再不修改被装饰函数源代码的情况下为其添加功能)
  • 不能修改被装饰的函数的调用方式
实现装饰器功能知识储备:
  • 函数既“变量”

    • 函数的参数可以接收变量,也可以接受函数,这里引用函数即变量的概念

在python里面函数就是一个变量,函数名就是一个变量,这个函数名里面存的是这个函数的内存地址,它把函数体放到内存里,在调用的时候从函数名里面的这个内存地址找到函数体然后运行这个函数。前面的博客说函数的时候,说过函数名后面加上小括号就是调用这个函数,如果只写这个函数名的话,打印一下就是这个函数的内存地址。

1 def test():
2     print('Hello Word')
3
4
5 print(test)  # 打印函数的内存地址 #<function test at 0x100662e18>
6 test()  # 调用函数

  • 高阶函数

    • 把一个函数名当做实参传给另外一个函数
    • 返回值中包含函数名(不修改函数的调用方式) *是不是不理解很懵逼,没事,一会用到*
    • 当传递函数作为变量时,被称为高阶函数
 1 import time
 2 def bar():
 3     time.sleep(3)
 4     print('in the  bar !!')
 5
 6 def test1(func):
 7     start_tiem = time.time()
 8     func()# run bar()
 9     stop_time = time.time()
10     print('the func run time is %s' %(stop_time-start_tiem))
11 test1(bar)

强行插入知识点: 嵌套函数

 1 def fun():
 2     print('in fun ')
 3     def bar(): #函数的嵌套
 4         print('in the bar ')
 5     bar()
 6 fun()
 7 #--------------------------#
 8 name = "Baylor"
 9 def change_name():
10
11     name = "Baylor2"
12     def change_name2():
13         name = "Baylor3"
14         print("第3层打", name)
15
16     change_name2()  # 调用内层函数
17     print("第2层打印", name)
18
19 change_name()
20 print("最外层打印", name)

嵌套函数中的作用域顺序-由内而外的寻找符合要求的参数

第一个装饰器

但每一次都需要从新对 test1 进行函数赋值,我们只需要通过装饰器的特殊书写方式,在需要增加新功能的函数上增加“@装饰器函数名”就可以完成装饰器的使用

 1 def timer(func):
 2     def deco():#函数的嵌套 timer(test1) func = test1
 3         start_time = time.time()
 4         func()  #run test1
 5         stop_time = time.time()
 6         print(' the func time is %s'%(stop_time - start_time))
 7     return deco  #高阶函数- 返回值中包含函数名
 8
 9 @timer   # test1 = timer(test1)
10 def test1():
11     time.sleep(3)
12     print('in the test1')
13 @timer
14 def test2():
15     time.sleep(2)
16     print('in the test2')
17
18 #test1 = timer(test1)
19 test1()# --->deco
20 test2()
21 print(timer(test1)) #打印test1 内存地址

所以我们说:高阶函数+嵌套函数 =>装饰器 ,我们通过高阶函数+函数嵌套实现了以上的装饰器,他符合不改变调用方式,为函数增加新功能。

问题:被装饰的函数如果有参数呢?

 1 def w1(func):
 2     def inner(arg):
 3         # 验证1
 4         # 验证2
 5         # 验证3
 6         return func(arg)
 7     return inner
 8
 9 @w1
10 def f1(arg):
11     print ('f1')
12
13
14 def w1(func):
15     def inner(arg1,arg2,arg3):
16         # 验证1
17         # 验证2
18         # 验证3
19         return func(arg1,arg2,arg3)
20     return inner
21
22 @w1
23 def f1(arg1,arg2,arg3):
24     print ('f1')

问题:可以装饰具有处理n个参数的函数的装饰器?

 1 def w1(func):
 2     def inner(*args, **kwargs):
 3         # 验证1
 4         # 验证2
 5         # 验证3
 6         print(*args,**kwargs)
 7
 8         return func(*args, **kwargs)
 9     return inner
10
11 @w1
12 def f1(arg1, arg2, arg3):
13     print('f1')
14
15 f1(1,2,3)

如果要装饰的函数带有参数时,因为你也不知道到底被装饰的函数会传什么参数,所以可以使用可变参数和关键字参数来接收所有的参数

 1 import time
 2 def timer(func):
 3     def deco(*args,**kwargs):#函数的嵌套 timer(test1) func = test1
 4         start_time = time.time()
 5         func(*args,**kwargs)  #run test1
 6         stop_time = time.time()
 7         print(' the func time is %s'%(stop_time - start_time))
 8     return deco  #高阶函数
 9
10 @timer   # test1 = timer(test1)
11 def test1():
12     time.sleep(3)
13     print('in the test1')
14 @timer  # test2 = timer(test2) = deco test2(name) = deco(name)
15 def test2(name,arg):
16     time.sleep(2)
17     print('in the test2 %s %s',name,arg)
18
19 test1()# --->deco
20 test2('Baylor',28)

在函数的传递参数过程中,我们的装饰器不能满足带参数的传递,以上,实现了当函数有参数传递的过程中也可以实现装饰器的新功能

终极函数装饰-补充知识

 1 import time
 2 user,passwd = 'jinyu','abc123'
 3 def auth(auth_type):
 4     def outer_wrapper(func):
 5         print('auth func:',auth_type)
 6         def wrapper(*args,**kwargs):
 7             print('------',auth_type)
 8             if auth_type =='local':
 9                 username = input('Username:')
10                 password = input('Password')
11                 if user == username and passwd == password:
12
13                     print('\033[31;1mUser  has password authentication\033[0m')
14                     # res = func(*args,**kwargs)
15                     res = func(*args,**kwargs) #1,2
16                     print('-----afte authentication-----',res)
17                     res.append(3)
18                     print(res)
19                     return res,'方法已运行完毕' # 结果
20                 else:
21                     print('\033[32;1m Invalid username or password\033[0m')
22             elif auth_type =='ldap':
23                 print('哈哈哈哈哈哈!!!ldap')
24         return wrapper
25     return outer_wrapper
26
27 def index():
28     print('welcome to index page!')
29 @auth(auth_type = 'local')#home  = wraapper
30 def home():
31     print('welcome to home page!')
32     return [1,2]
33 @auth(auth_type = 'ldap')
34 def bbs():
35     print('welcome to bbs page!')
36
37 index()
38 home()
39 # bbs()

三层函数形成了终结装饰器,通过装饰器所传的参数能够进行装饰器功能判断,提供了更好的扩展性

列表生成式-作用:使代码更加简洁

1 a = [i*2 for i in range(10)]   #列表生成式 3行代码一行搞定
2 print(a)
3
4 a = []
5 for i in range(10):
6     a.append(i*2)
7 print(a)

生成器

  • 只有在调用时才会生成相应的数据----生成器:你用到这个里面的数据的时候它才会生成,这样就比较省内存,因为是需要这个值的时候,才会在内存里面产生
  • 只记录当前位置,只有一个__next__()方法 2.7next()
1 a =(i * 2 for i in range(10)) #如果要打印generator中的元素需要借助next方法  需要循环才能取出
2 # a =[i * 2 for i in range(10)] # list的元素我们可以一个个打印出,
3 print(a) #<generator object <genexpr> at 0x10228f2b0>
4 print(next(a))
5 print(next(a))
6 print(a.__next__())7 print(a.__next__())

小练习-斐波那契数列

 1 def fib(max):
 2     n, a, b = 0, 0, 1
 3     while n < max:
 4         print(b)
 5         a, b = b, a + b  # t(b,a+b) a=t[0]-1 b=t[1]-2    a+b等同于 t的下标相加
 6         n = n + 1
 7     return 'done'  # 无用
 8
 9
10 fib(10)
11
12 # 如果把这个改进成 yield 生成器,通过 __next__调用 只需要 把print(b) 改成 yield b 即可
13 temp = []
14
15
16 def fib(max):
17     n, a, b = 0, 0, 1
18     while n < max:
19         yield b
20         a, b = b, a + b  # t(b,a+b) a=t[0]-1 b=t[1]-2    a+b等同于 t的下标相加
21         n = n + 1
22     return 'done'  # 无用
23
24 x = fib(10)
25 print(x)
26 print(x.__next__())
27 print(x.__next__())
28 print(x.__next__())
29 print(x.__next__()) 

匿名函数 ---也叫 lambda函数

 1 #匿名函数就是不需要显式的指定函数
 2
 3 # 这段代码
 4 def calc(n):
 5     return n * n
 6
 7 print(calc(10))
 8
 9 # 换成匿名函数
10 calc = lambda n: n * n
11 print(calc(10))
12 #你也许会说,用上这个东西没感觉有毛方便呀, 。。。。呵呵,如果是这么用,确实没毛线改进,不过匿名函数主要是和其它函数搭配使用的呢,如下
13 #x=[1, 5, 7, 4, 8]
14 res = map(lambda x: x * 2, [1, 5, 7, 4, 8]) #map会根据提供的函数对指定序列做映射。
15 for i in res:
16     print(i)#匿名函数只能处理比较简单的处理逻辑,只能写简单的表达式,不能写循环 判断,比如三元运算符

json 处理

json是一种所有语言中都通用的key-value数据结构的数据类型,很像python中的字典,json处理使用json模块,json模块有下面常用的方法:

 1 import json
 2
 3 dic = {"name": "niuniu", "age": 18}
 4 print(json.dumps(dic))  # 把字典转成json串
 5 fj = open('a.json', 'w')
 6 print(json.dump(dic, fj))  # 把字典转换成的json串写到一个文件里面
 7 s_json = '{"name":"niuniu","age":20,"status":true}'
 8 print(json.loads(s_json))  # 把json串转换成字典
 9
10 # 先创建b.json文件 运行运行此代码*{"name": "chenjianguo", "age": 18}*
11 fr = open('b.json', 'r')
12 print(json.load(fr))  # 从文件中读取json数据,然后转成字

首先说明基本功能:
  • dumps是将dict转化成str格式,loads是将str转化成dict格式。
  • dump和load也是类似的功能,只是与文件操作结合起来了。
  • dump 是把字典转成son串格式写   load是把json串转成字典读-(json必须双引号)

  内置函数详细介绍 https://docs.python.org/3/library/functions.html?highlight=built#ord

资料补充

生成器并行

 1 import time
 2 def consumer(name):
 3     print('%s 我准备吃包子了'%name)
 4     while True:
 5         baozi = yield #保存当前状态返回,
 6         print('包子[%s]来了,被[%s]吃了'%(baozi,name))
 7 # c = consumer('houzi')
 8 # c.__next__()
 9 #b = '韭菜馅'
10 #c.send(b) # 调用yield  并传值
11 #c.__next__()
12 def producer(name):
13     c = consumer('A')  #生成
14     c2 = consumer('B')
15     c.__next__()
16     c2.__next__()
17     print('开始准备做包子了。。。。。。')
18     for i in range(10):
19         time.sleep(1)
20         print('做了2个包子!!!!')
21         c.send(i)
22         c2.send(i)
23
24 producer('houzi')

使用类来写装饰器-强势插入新知识

分享一下,需要用类里面的__call__方法,__call__方法就是可以把这个实例当成一个函数来调用,如果正常使用类里面的方法的话,实例方法要先实例化类,然后才能调用,静态方法、类方法则需要用类名或者实例化之后的对象来调用,而实例化之后的这个对象,是不能被调用的,__call__方法就是把这个实例变成一个可以调用的对象,也就是说实例化之后,这个对象就可以和一个普通函数一样被调用。

1 class Foo:
2     def __call__(self, *args, **kwargs):
3         print('call....')
4     def test(self):#
5         print('test....')
6 if __name__ == '__main__':
7     t = Foo()#实例化类
8     t.test()#正常调用实例方法
9     t()#直接调用实例化之后的对象

理解了上面的之后,就可以使用class来写一个装饰器了,计算程序的运行时间,当然思想和以前用函数写装饰器是一样的
 1 class Fuck(object):
 2     def __init__(self, func):
 3         self.func = func
 4     def __call__(self, *args, **kwargs):
 5         import time
 6         start_time = time.time()
 7         res = self.func(*args, **kwargs)
 8         end_time = time.time()
 9         print('the function "%s" run time is %s' % (self.func.__name__,
10                                                     (end_time - start_time)))
11         return res
12 @Fuck
13 def run(name):
14     import time
15     time.sleep(1)
16     return 'sb_%s' % name
17 print(run('hyf'))

转载于:https://www.cnblogs.com/Baylor-Chen/p/9046641.html

Python装饰器、生成器、内置函数、Json-Day05相关推荐

  1. Python装饰器、内置函数之金兰契友

    装饰器:装饰器的实质就是一个闭包,而闭包又是嵌套函数的一种.所以也可以理解装饰器是一种特殊的函数. 因为程序一般都遵守开放封闭原则,软件在设计初期不可能把所有情况都想到,所以一般软件都支持功能上的扩展 ...

  2. python装饰器 稀里糊涂_万恶之源 - Python装饰器及内置函数

    装饰器 听名字应该知道这是一个装饰的东西,我们今天就来讲解一下装饰器,有的铁子们应该听说,有的没有听说过.没有关系我告诉你们这是一个很神奇的东西 这个有多神奇呢? 我们先来复习一下闭包 def fun ...

  3. python中的json函数_python中装饰器、内置函数、json的详解

    装饰器 装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象. 先看简单例子: def run(): time.sleep(1 ...

  4. 五、python函数、装饰器、内置函数、json及模块

    一.递归调用 1.一个函数自己调用自己就是递归调用,最多一个函数递归调用自己999次,超过就会出错 2.递归必须有一个明确的结束条件 3.每次进入更深一层递归时,问题规模相比上次递归都应有所减少 4. ...

  5. 13装饰器和内置函数

    装饰器 # 1.装饰用的工具# import time #内置函数计算函数运行时间 # print(time.time())# import time # def func(): # start_ti ...

  6. python自动化_day4_迭代器生成器内置函数和匿名函数

    什么是可迭代的 含有__iter__方法的就是可迭代的: python 可迭代对象--Iterable Python中经常使用for来对某个对象进行遍历,此时被遍历的这个对象就是可迭代对象, 像常见的 ...

  7. Python装饰器是什么?使用Python装饰器实现计算程序(函数)运行时间的功能

    Python装饰器是什么?使用Python装饰器实现计算程序(函数)运行时间的功能 目录

  8. Python标准库:内置函数dict(mapping, **kwarg)

    Python标准库:内置函数dict(mapping, **kwarg) 本函数是从一个映射函数对象构造一个新字典. 与dict(**kwarg)函数不一样的地方是參数输入是一个映射类型的函数对象,比 ...

  9. python文档整理,Python官方文档内置函数整理Word版

    <Python官方文档内置函数整理Word版>由会员分享,可在线阅读,更多相关<Python官方文档内置函数整理Word版(6页珍藏版)>请在人人文库网上搜索. 1.传播优秀W ...

  10. 【Python养成】常用内置函数 — 2(详解25个内置函数)

    图片来自互联网 文章目录 前言 二.内置函数详解 1.函数:chr(x) 2.函数:dir([obj]) 3.函数:divmod(x,y) 4.函数:enumerate(sequence, [star ...

最新文章

  1. jawstats php,JAWStats 配置(为AWStats配上华丽的外衣)
  2. PTP4L命令手册(谷歌翻译)
  3. Office365 Exchange Hybrid No.15 DNS切换及邮件传输排错
  4. No identifier specified for entity
  5. YOLOv5-LibTorch
  6. spring boot(一):入门篇
  7. java 自旋锁_java锁的种类以及辨析(一):自旋锁
  8. 5G与WiFi 6之争,对物联网意味着什么
  9. php安装文件怎么打开文件_我的php文件怎么打开_如何打开php文件的办法
  10. libcurl使用easy模式阻塞卡死等问题的完美解决---超时设置
  11. 灵活就业协议影响应届身份吗,档案应该如何处理
  12. java8 新特性_Java8新特性系列之-日期处理详解(二)
  13. OpenMP与C++ 事半功倍地获得多线程的好处 下
  14. ArcGIS数据生产与精细化制图之中国年降水量分布图的制作
  15. macbook历代_你都见过吗?苹果Mac历代台式机回忆录
  16. 运行jar文件,jar程序闪退,cmd命令行黑框一闪而过,无法启动jar文件
  17. CSAPP 第三版 第四章 家庭作业and so on
  18. 优秀码农选择对象详细指南,看完记得要实战噢
  19. 中国浓缩咖啡机行业市场供需与战略研究报告
  20. 文化袁探索专栏——事件分发机制

热门文章

  1. SpringBoot中的Quartz应用
  2. DHCP冲突的解决方法
  3. vsftp建立虚拟用户不同目录分配不同权限操作步骤详解
  4. 【MFC两种视频图像採集方法】DirectShow与Opencv
  5. ant 编译android工程(转)
  6. WebSphere通过corba调Tuxedo问题(2)
  7. 血压测量:很重要的事情!
  8. C# 计时函数精度测试
  9. C#new出来的结构体内存分配在堆上
  10. TrinityCore3.3.5编译过程-官方指导-踩坑总结