Day 14
1.推导式:通过一行循环判断,遍历一系列数据的方式
''' 推导式的语法:val for val in Iterable三种方式:[val for val in Iterable]{val for val in Iterable}{k:v for k,v in Iterable} '''
#列表里面需要100条数据
lst=[]
for i in range(1,101):lst.append(i)
print(lst)
#基本语法
lst=[i for i in range(1,101)]
print(lst)
#单循环推导式
lst=[1,2,3,4,5,6,7]
lst_new=[]
for i in lst:res=i*3lst_new.append(res)
print(lst_new)
#改写成推导式
lst=[i*3 for i in lst]
print(lst)
#带有判断条件的单循环推导式(只能是单向分支,接在for后面)
lst=[1,2,3,4,5,6,7,8,9]
lst_new=[]
for i in lst:if i % 2 ==1:lst_new.append(i)
print(lst_new)
#改写成推导式
lst=[i for i in lst if i % 2 == 1]
print(lst)
#双循环推导式
lst1 = ["李博伦","高云峰","孙致和","葛龙"]
lst2 = ["李亚","刘彩霞","刘子豪","刘昕"]
#谁'爱'谁
lst_new=[]
for i in lst1:for j in lsts2:if lst1.index(i)==lst2.index(j):strvar=i+'爱'+jlst_new.append(strvar)
print(lst_new)
#改写成推导式
lst=[i+'爱'+j for i in lst1 for j in lst2 if lst1.index(i)==lst2.index(j)]
print(lst)
2.字典集合推导式
""" 案例:满足年龄在18到21,存款大于等于5000 小于等于5500的人,开卡格式为:尊贵VIP卡老x(姓氏),否则开卡格式为:抠脚大汉卡老x(姓氏) 把开卡的种类统计出来 """
listvar = [{"name":"刘鑫炜","age":18,"money":10000},{"name":"刘聪","age":19,"money":5100},{"name":"刘子豪","age":20,"money":4800},{"name":"孔祥群","age":21,"money":2000},{"name":"宋云杰","age":18,"money":20}
]
#常规写法
strvar=set()
for i in listvarij 18 <= i['age']<= 21 and 5000 <= i['money']<=5500:res='最贵vip卡老'+i['name'][0]else:res='抠脚大汉卡老'+i['name'][0]setvar.add(res)
print(setvar)
#改写成集合推导式
setvar={'尊贵VIP卡老'+i['name'][0] if 18 <= i ['age']<=21 5000 <= i['money']<=5500 else '抠脚大汉卡老'+ i['name'][0] for i in listvar}
print(setvar)
# ###字典推导式
#enumerate
''' ennumerate(itersble,[start=0]) 功能:枚举;将索引号和iterable中的值,一个一个拿出来配对组成元组放入迭代器 参数:iterable:可迭代性数据(常用:迭代器,容器类型数据,可迭代对象range)start:可以选择开始的索引号默认从0开始索引 返回值:迭代器 '''
from collections import Iterator
lst=['东邪','西毒','南帝','北丐']
#基本使用
it=enumerate(lst)
print(isinstance(it,Iterator)
#for next
for i in range(4)print(next(it))
#list
'''start可以指定开始值,默认是0'''
it=enumerate(lst,start=1)
print(list(it))'
#encumerate 形成字典推导式,变成字典
dic={k:v for k,v in enumerate(lst,start=1)}
print(dic)
# dict 强转变成字典
dic=dict(enumerate(lst,atart=1))
print(dic)
# zip
''' zip(Iterable , ....) 功能:将多个iterable中的值,一个一个拿出来配对组成元组放入迭代器中 Iterable:可迭代性数据 返回:迭代器 特征:如果找不到对应的配对元素,当前元素会被舍弃 '''
lst1 = ["晏国彰","刘子涛","郭凯","宋云杰"]
lst2 = ["刘有右柳翔","冯雍","孙志新"]
lst3 = ["周鹏飞","袁伟倬"]
it = zip(lst1,lst2,lst3)
print(isinstance(it,Iterator))
print(list(it))
#zip 形成字典推导式,变成字典
lst1 = ["晏国彰","刘子涛","郭凯","宋云杰"]
lst2 = ["刘有右柳翔","冯雍","孙志新"]
dic ={k:v for k,v in zip(lst1,lst2)}
print(dic)
#dict 强转字典
dic=dict(zip(lst1,lst2))
print(dic)
3.生成器表达式
生成器的本质就是迭代器,允许自定义逻辑的迭代器
迭代器和生成器的区别:
迭代器本身是系统内置的,重写不了,二生成器是用户自定义的,可以重写迭代逻辑
生成器可以用两种方式创建:
(1)生成器表达式:里面是推导式,外面用圆括号
(2)生成器函数:用def定义,里面有yield
from collections import Iterable,Iterator
#生成器表达式
gen =(i*2 for i in range(1,11))
print(isinstance(gen,Iterator))
#next
res=next(gen)
print(res)
#for
for i in gen :print(i)
#for next
gen=(i*2 for i in range(1,11))
for i in range(3):res=next(gen)print(res)
#list
res=list(gen)
print(res)
4.生成器函数
yield 类似于 return
共同点在于:执行到这就话都会把值返回回去
不同点在于:yield每次返回时,会记得上次离开执行的位置,下次再调用生成器,会从上次执行的位置往下走而return直接终止函数,每次从头调用
from collections import Iterable,Iterator
#生成器函数的基本语法
#定义一个生成器函数
def mygen():print(111)yield 1print(222)yield 2print(333)yield 3
#初始化生成器函数,返回生成器对象,简称生成器
gen=mygen
print(isinstance(gen,Iterstor))
#使用next调用
res=next(gen)
print(res)
res=next(gen)
print(res)
res=next(gen)
print(res)
""" 代码解析: 初始化生成器函数 -> 生成器(通过next调用) 第一次调用生成器 res = next(gen) => print(111) yield 1 保存当前代码状态14行,并将1这个值返回 print(1) ,等待下一次调用 第二次调用生成器 res = next(gen) => 从上一次保存的状态14行继续向下执行 print(222) yield 2 保存当前代码状态17行,并将2这个值返回 print(2) ,等待下一次调用 第三次调用生成器 res = next(gen) => 从上一次保存的状态17行继续向下执行 print(333) yield 3 保存当前代码状态20行,并将3这个值返回 print(3) ,等待下一次调用 第四次调用生成器 因为没有更多yield返回数据了,所以直接报错. """
#优化代码1
def mygen():for i in range(1,101):yield '该球衣的号码是{}'.format(i)
#初始化生成器函数
gen=mygen()
# for next 调用数据
for i in range(50):res=next(gen)print(res)
for i in range(30):res=next(gen)print(res)
#send 用法
''' next 和 sent 区别next 只能取值send 不但能取值,还能发送值 send注意点:第一个send不能给yield传值 默认只能写None最后一个yield接受不到send的发送值send是给上一个yield发送值 '''
def mygen():print("process start")res = yield 100print(res,"内部打印1")res = yield 200print(res,"内部打印2")res = yield 300print(res,"内部打印3")print("process end")# 初始化生成器函数 -> 生成器
gen = mygen()
# 在使用send时,第一次调用必须传递的参数是None(硬性语法),因为第一次还没有遇到上一个yield
'''第一次调用'''
res = gen.send(None) #<=> next(gen)
print(res)
'''第二次调用'''
res = gen.send(101) #<=> next(gen)
print(res)
'''第三次调用'''
res = gen.send(201) #<=> next(gen)
print(res)
'''第四次调用, 因为没有更多的yield返回数据了,所以StopIteration'''
""" res = gen.send(301) #<=> next(gen) print(res) """""" # 代码解析: 初始化生成器函数,返回生成器对象 第一次调用时, print("process start") res = yield 100 记录当前代码状态81行,返回100,等待下一次调用 res = 100 print(100)第二次调用时, 把101 发送给上一个yield保存的状态81行 res = 101 从81行继续往下走 print(101,"内部打印1") res = yield 200 记录当前代码状态84行,返回200,等待下一次调用 res = 200 print(200)第三次调用时, 把201 发送给上一个yield保存的状态84行 res = 201 从84行继续往下走 print(201,"内部打印2") res = yield 300 记录当前代码状态87行,返回300,等待下一次调用 res = 300 print(300) """# 4.yield from : 将一个可迭代对象变成一个迭代器返回 def mygen():yield from ["马生平","刘彩霞","余锐","晏国彰"]gen = mygen()
print(next(gen))
print(next(gen))
print(next(gen))
print(next(gen))# 5.用生成器描述斐波那契数列
"""1 1 2 3 5 8 13 21 34 ... """
""" yield 1 a,b = b,a+b = 1,1yield 1 a,b = b,a+b = 1,2yield 2 a,b = b,a+b = 2,3yield 3 a,b = b,a+b = 3,5yield 5 ...."""def mygen(maxlen):a,b = 0,1i = 0while i < maxlen:yield ba,b = b,a+bi+=1# 初始化生成器函数 -> 生成器
gen = mygen(10)for i in range(3):print(next(gen))