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*3
lst_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+'爱'+j
lst_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 listvar
ij 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 1
print(222)
yield 2
print(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 100
print(res,"内部打印1")
res = yield 200
print(res,"内部打印2")
res = yield 300
print(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,1
yield 1
a,b = b,a+b = 1,2
yield 2
a,b = b,a+b = 2,3
yield 3
a,b = b,a+b = 3,5
yield 5
....
"""
def mygen(maxlen):
a,b = 0,1
i = 0
while i < maxlen:
yield b
a,b = b,a+b
i+=1
# 初始化生成器函数 -> 生成器
gen = mygen(10)
for i in range(3):
print(next(gen))