8.02_python_lx_day14
一.推导式 : 通过一行循环判断,遍历一系列数据的方式
推导式的语法:
val for val in Iterable
三种方式:
[val for val in Iterable]
{val for val in Iterable}
{k:v for k,v in Iterable}
(1)列表里面需要100条数据
①普通写法
1 lst = []
2 for i in range(1,101):
3 lst.append(i)
4 print(lst)
②列表推导式基本语法
1 lst = [i for i in range(1,101)]
2 print(lst)
(2)单循环推导式 [1,2,3,4,5] -> [3,6,9,12,15]
①普通写法
1 lst = [1,2,3,4,5]
2 lst_new = []
3 for i in lst:
4 res = i * 3
5 lst_new.append(res)
6 print(lst_new)
②改写成推导式
1 lst = [i*3 for i in lst]
2 print(lst)
(3)带有判断条件的单循环推导式 (只能是单项分支,接在for后面)
①普通写法
1 lst = [1,2,3,4,5,6,7,8]
2 lst_new = []
3 for i in lst:
4 if i % 2 == 1:
5 lst_new.append(i)
6 print(lst_new)
②改写成推导式
1 lst = [i for i in lst if i % 2 == 1]
2 print(lst)
(4)双循环推导式
①普通写法
1 lst1 = ["1","2","3","4"]
2 lst2 = ["a","b","c","d"]
3 lst_new = []
4 for i in lst1:
5 for j in lst2:
6 strvar = i + "❤" + j
7 lst_new.append(strvar)
8 print(lst_new)
②改写成推导式
1 lst1 = ["1","2","3","4"]
2 lst2 = ["a","b","c","d"]
3 lst = [i + "❤" + j for i in lst1 for j in lst2]
4 print(lst)
(5) 带有判断条件的多循环推导式
①普通写法
1 lst1 = ["1","2","3","4"]
2 lst2 = ["a","b","c","d"]
3 lst_new = []
4 for i in lst1:
5 for j in lst2:
6 if lst1.index(i) == lst2.index(j):
7 strvar = i + "❤" + j
8 lst_new.append(strvar)
9 print(lst_new)
②改写成推导式
1 lst1 = ["1","2","3","4"]
2 lst2 = ["a","b","c","d"]
3 lst = [ i + "❤" + j for i in lst1 for j in lst2 if lst1.index(i) == lst2.index(j) ]
4 print(lst)
二.集合推导式
案例:
满足年龄在18到21,存款大于等于5000 小于等于5500的人,
开卡格式为:尊贵VIP卡老x(姓氏),否则开卡格式为:抠脚大汉卡老x(姓氏)
把开卡的种类统计出来
listvar = [
{"name":"刘11","age":18,"money":10000},
{"name":"刘22","age":19,"money":5100},
{"name":"刘33","age":20,"money":4800},
{"name":"孔44","age":21,"money":2000},
{"name":"宋55","age":18,"money":20}
]
①常规写法
1 setvar = set()
2 for i in listvar:
3 if 18 <= i["age"] <= 21 and 5000 <= i["money"] <= 5500:
4 res = "尊贵VIP卡老" + i["name"][0]
5 else:
6 res = "抠脚大汉卡老" + i["name"][0]
7 setvar.add(res)
8 print(setvar)
②改写成三元运算符 + 集合推导式
1 setvar = { "尊贵VIP卡老" + i["name"][0] if 18 <= i["age"] <= 21 and 5000 <= i["money"] <= 5500 else "抠脚大汉卡老" + i["name"][0] for i in listvar }
2 print(setvar)
三.字典推导式
(1)enumerate
enumerate(iterable,[start=0])
功能:枚举 ; 将索引号和iterable中的值,一个一个拿出来配对组成元组放入迭代器中
参数:
iterable: 可迭代性数据 (常用:迭代器,容器类型数据,可迭代对象range)
start: 可以选择开始的索引号(默认从0开始索引)
返回值:迭代器
1 from collections import Iterator
2 lst = ["东邪","西毒","南帝","北丐"]
①基本使用
1 it = enumerate(lst)
2 print(isinstance(it,Iterator))
②list
1 #start可以指定开始值,默认是0
2 it = enumerate(lst,start=1)
3 print(list(it))
③enumerate 形成字典推导式 变成字典
1 dic = { k:v for k,v in enumerate(lst,start=1) }
2 print(dic)
④dict 强制变成字典
1 dic = dict(enumerate(lst,start=1))
2 print(dic)
(2)zip
zip(iterable, ... ...)
功能: 将多个iterable中的值,一个一个拿出来配对组成元组放入迭代器中
iterable: 可迭代性数据 (常用:迭代器,容器类型数据,可迭代对象range)
返回: 迭代器
特征: 如果找不到对应配对的元素,当前元素会被舍弃
<1>基本使用
1 lst1 = ["a","b","c","d"]
2 lst2 = ["1","2","3"]
3 lst3 = ["$","%"]
4 it = zip(lst1,lst2)
5 it = zip(lst1,lst2,lst3)
6 print(isinstance(it,Iterator))
7 print(list(it))
<2>zip 形成字典推导式 变成字典
1 lst1 = ["a","b","c","d"]
2 lst2 = ["1","2","3"]
3 dic = { k:v for k,v in zip(lst1,lst2) }
4 print(dic)
<3>dict 强制变成字典
1 dic = dict(zip(lst1,lst2))
2 print(dic)
四.生成器表达式
生成器本质是迭代器,允许自定义逻辑的迭代器
迭代器和生成器区别:
迭代器本身是系统内置的.重写不了.而生成器是用户自定义的,可以重写迭代逻辑
生成器可以用两种方式创建:
(1)生成器表达式 (里面是推导式,外面用圆括号)
(2)生成器函数 (用def定义,里面含有yield)
from collections import Iterator,Iterable
(1)生成器表达式
1 gen = (i*2 for i in range(1,11))
2 print(isinstance(gen,Iterator))
3 print(list(gen))
五.生成器函数
yield 类似于 return
共同点在于:执行到这句话都会把值返回出去
不同点在于:yield每次返回时,会记住上次离开时执行的位置 , 下次在调用生成器 , 会从上次执行的位置往下走
而return直接终止函数,每次重头调用.
yield 6 和 yield(6) 2种写法都可以 yield 6 更像 return 6 的写法 推荐使用
(1) 生成器函数的基本语法
<1>定义一个生成器函数
1 def mygen():
2 print(111)
3 yield 1
4 print(222)
5 yield 2
6 print(333)
7 yield 3
<2> 初始化生成器函数,返回生成器,简称生成器
1 gen = mygen()
2 print(isinstance(gen,Iterator))
<3>使用next调用
1 res = next(gen)
2 print(res)
(2)优化代码
1 def mygen():
2 for i in range(1,101):
3 yield "该球衣号码是{}".format(i)
初始化生成器函数 -> 生成器
1 gen = mygen()
for + next 调用数据
1 for i in range(50):
2 res = next(gen)
3 print(res)
(3)send 用法
next和send区别:
next 只能取值
send 不但能取值,还能发送值
send注意点:
第一个 send 不能给 yield 传值 默认只能写None
最后一个yield 接受不到send的发送值
send 是给上一个yield发送值
<1>
1 def mygen():
2 print("process start")
3 res = yield 100
4 print(res,"内部打印1")
5
6 res = yield 200
7 print(res,"内部打印2")
8
9 res = yield 300
10 print(res,"内部打印3")
11 print("process end")
<2>初始化生成器函数 -> 生成器
gen = mygen()
<3>在使用send时,第一次调用必须传递的参数是None(硬性语法),因为第一次还没有遇到上一个yield
第一次调用
1 res = gen.send(None) #<=> next(gen)
2 print(res)
第二次调用
1 res = gen.send(101) #<=> next(gen)
2 print(res)
第三次调用
1 res = gen.send(201) #<=> next(gen)
2 print(res)
第四次调用, 因为没有更多的yield返回数据了,所以StopIteration
1 res = gen.send(301) #<=> next(gen)
2 print(res)
(4)yield from : 将一个可迭代对象变成一个迭代器返回
1 def mygen():
2 yield from ["1","2","3","4"]
3 gen = mygen()
4 print(next(gen)) #1
5 print(next(gen)) #2
6 print(next(gen)) #3
7 print(next(gen)) #4
(5)用生成器描述斐波那契数列
1 1 2 3 5 8 13 21 34 ...
1 yield 1
2 a,b = b,a+b = 1,1
3 0 1
4 yield 1
5 a,b = b,a+b = 1,2
6
7 yield 2
8 a,b = b,a+b = 2,3
9
10 yield 3
11 a,b = b,a+b = 3,5
12
13 yield 5
1 def mygen(maxlen):
2 a,b = 0,1
3 i = 0
4 while i < maxlen:
5 yield b
6 a,b = b,a+b
7 i+=1
初始化生成器函数 -> 生成器
1 gen = mygen(10)
2 for i in range(3):
3 print(next(gen))
it = enumerate(lst)print(isinstance(it,Iterator))