day11:装饰器(装饰器形成、装饰器作用、@语法糖、原则、固定模式)
-
装饰器形成:最简单的、有返回值的、有一个参数的、万能参数
- 函数起的作用:装饰器用于在已经完成的函数前后增加功能
- 语法糖:使代码变得简单
- 原则:开放封闭原则,因为已经发布的源码不可以轻易修改,所以使用装饰器在原来的基础上增加功能呢个
- 固定模式、万能参数、有返回值
-
1 import time 2 def timmer(func): 3 def inner(*args,**kwargs): 4 start = time.time() 5 time.sleep(1) 6 ret = func(*args,**kwargs) 7 end = time.time() - start 8 return ret,end 9 return inner 10 11 12 @timmer 13 def func(i): 14 print(i) 15 return '***:%s' %i 16 17 res = func('w') 18 n,t = res 19 print(n,t)
- 练习题
- 编写装饰器、为多个函加上认证功能()
1 FLAG = False 2 def timmer(func): 3 global FALG 4 def inner (*args,**kwargs): 5 start = time.time() 6 if FLAG: 7 res = func() 8 else: 9 res = '登录失败' 10 return res 11 return inner 12 13 def Login(): 14 login_user = input('请输入账号:') 15 login_pass = input('请输入密码:') 16 with open('user.txt','r',encoding='utf-8') as f: 17 for i in f: 18 if 'login_user' in i: 19 user_name,user_pass = '|'.join(i) 20 break 21 if login_user == user_name and login_pass == user_pass: 22 global FLAG 23 FLAG = True 24 else: 25 print('登录失败') 26 continue 27 28 29 @timmer 30 def func(a,b): 31 print(a,b) 32 return '***:%s;***%s' %(a,b) 33 34 while 1: 35 command = input('请输入操作序号:]\n1:登录\n2:执行') 36 if command == '1': 37 Logon() 38 elif command == '2': 39 func() 40 else: 41 print('您的输入有误,请重新输入') 42 continue
- 编写装饰器,为多个函数加上记录调用功能,要求每次调用函数都将被调用的函数名称写入文件
- 编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果
- 为题目3编写装饰器,实现缓存网页内容的功能:
- 编写装饰器、为多个函加上认证功能()
day12:装饰器的进阶(wraps模块、进阶)
- wraps模块
- 作用:当一个函数被装饰后,使用__name__ 和 __doc__查看函数相关信息时,会查看装饰器的相关信息,wraps的作用就是查看信息时查看的是被点用函数的相关信息
- 例子:
1 from functools import wraps 2 3 4 def timmer(func): 5 @wraps(func) 6 def inner(*args,**kwargs): 7 """这个是inner""" 8 res = func(*args,**kwargs) 9 return res 10 return inner 11 12 13 @timmer 14 def func1(a,b): 15 """这个是func1""" 16 print(a,b) 17 return '%s *** %s' % (a,b) 18 19 20 print(func1.__name__) 21 print(func1.__doc__)
- 装饰器进阶
- 多个函数怎么同时决定是否使用装饰器
1 from functools import wraps 2 FLAGE = True 3 4 def timmer(flage): 5 def wrapper(func): 6 @wraps(func) 7 def inner(*args,**kwargs): 8 if flage: 9 print('装饰前被执行前做的事') 10 res = func(*args,**kwargs) 11 print('装饰器被执行后做的事') 12 return res 13 else: 14 res = func(*args,**kwargs) 15 return res 16 return inner 17 return wrapper 18 19 20 @timmer(FLAGE) 21 def func1(a,b): 22 print('执行了,收到了%s 和 %s' %(a,b)) 23 print(func1.__name__) 24 return 'Ok' 25 26 27 @timmer(FLAGE) 28 def func2(a,b): 29 print('执行了,收到了%s 和 %s' %(a,b)) 30 print(func2.__name__) 31 return 'Ok' 32 33 34 print(func1('董','轩')) 35 print(func2('Python','蟒蛇'))
- 一个函数被多个装饰器调用
1 def wrapper1(func): 2 def inner(*args,**kwargs): 3 print('wrapper1 start') 4 res = func(*args,**kwargs) 5 print(res) 6 print('wrapper1 end') 7 return res 8 return inner 9 10 11 def wrapper2(func): 12 def inner(*args,**kwargs): 13 print('wrapper2 start') 14 res = func(*args,**kwargs) 15 print(res) 16 print('wrapper2 end') 17 return res 18 return inner 19 20 21 def wrapper3(func): 22 def inner(*args,**kwargs): 23 print('wrapper3 start') 24 res = func(*args,**kwargs) 25 print(res) 26 print('wrapper3 end') 27 return res 28 return inner 29 30 31 @wrapper3 32 @wrapper2 33 @wrapper1 34 35 def func(): 36 print(func.__name__) 37 return 'Func执行完了' 38 39 40 41 print(func())
- 多个函数怎么同时决定是否使用装饰器
day13:(迭代器、生成器)
- 迭代器
- 从容其中一个一个取值,会把所有数据拿到
- 节省内存
- 迭代器协议和可迭代协议
- 可以被for循环的都是可迭代的
- 可迭代的内部都有__iter__方法
- 只要是迭代器,一定可以迭代
- 可迭代的.__iter__()就可以获取一个迭代器
- 迭代器中的__next__()方法可以一个一个的获取值
- 检验迭代器和可迭代的方法
1 from collections import Iterable 2 from collections import Iterator 3 print(isinstance([],Iterable)) 4 print(isinstance([],Iterator))
- 生成器
- 只要含有yield关键字的函数都是生成器函数
- yield不能和return共用且需要写在函数内
- 简单的一个生成器
1 def generator(): 2 print(1) 3 yield 'a' 4 5 6 # 取值 7 ret = generator() 8 print(ret.__next__())
day14:(生成器函数进阶、表达式、各种推导式)
- 生成器进阶
- send:获取下一个值的效果和next基本一致,第一次不能用send
- 例子
- 获取平均值
1 def average(): 2 sum = 0 3 count = 0 4 avg = 0 5 while True: 6 num = yield avg 7 sum += num # 10 8 count += 1 # 1 9 avg = sum/count 10 11 avg_g = average() 12 print(avg_g.__next__()) 13 avg1 = avg_g.send(10) 14 avg1 = avg_g.send(20) 15 avg1 = avg_g.send(30) 16 print(avg1)
- 预激活生成器,就是使用装饰器,让send可以第一次使用
1 def init(func): #装饰器 2 def inner(*args, **kwargs): 3 g = func(*args, **kwargs) #g = average() 4 g.__next__() 5 return g 6 return inner 7 8 @init 9 def average(): 10 sum = 0 11 count = 0 12 avg = 0 13 while True: 14 num = yield avg 15 sum += num # 10 16 count += 1 # 1 17 avg = sum/count 18 19 20 avg_g = average() #===> inner 21 ret = avg_g.send(10) 22 print(ret) 23 ret = avg_g.send(20) 24 print(ret)
- 小技巧
1 def generator(): 2 a = 'abcde' 3 b = '12345' 4 for i in a: 5 yield i 6 for i in b: 7 yield i 8 def generator(): 9 a = 'abcde' 10 b = '12345' 11 yield from a 12 yield from b 13 14 g = generator() 15 for i in g: 16 print(i)
- 获取平均值
- 生成器表达式
g = (i for i in range(10)) print(g) for i in g: print(i)
- 各种推导式
1 # 列表: 2 ret = [i*i for i in (1,2,3,4) if i%3 == 0] 3 print(ret) 4 例子: 5 找到嵌套列表中名字含有两个‘e’的所有名字 6 names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'], 7 ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']] 8 ret = [name for lst in names for name in lst if name.count('e') ==2] # 列表 9 ret = (name for lst in names for name in lst if name.count('e') ==2) # 字典 10 for i in ret: 11 print(i) 12 13 14 # 字典: 15 mcase = {'a': 10, 'b': 34} 16 mcase_frequency = {mcase[k]: k for k in mcase} 17 print(mcase_frequency) 18 19 #集合推导式,自带结果去重功能 20 squared = {x**2 for x in [1, -1, 2]} 21 print(squared)
day15:(面试题、内置函数)
- 面试题
一、 def demo(): for i in range(4): yield i g=demo() g1=(i for i in g) g2=(i for i in g1) print(list(g)) print(list(g1)) print(list(g2)) 二、 def add(n,i): return n+i def test(): for i in range(5): yield i g=test() for n in [1,10,5]: g=(add(n,i) for i in g) print(list(g))
- 内置函数:https://www.processon.com/view/link/5c35f503e4b0641c83d55651