day13 迭代器和生成器
一、迭代器
1.什么是迭代器(iter英文名)
1)迭代器是系统提供的容器型数据类型
2)创建迭代器:
a.将其他序列转换成迭代器
b.创建生成器
3)迭代器的特点:
a.打印不能列出查看到迭代器中的元素
b.不能通过len获取迭代器中元素的个数
c.如果要使用元素,必须先将元素从迭代器中取出来,而且额取出来之后就无法再放回去(取一个少一个)
i1= iter('abc')
print(i1)#<str_iterator object at 0x000001A39AF54580>
#--- 不能打印数据(类似有瓶盖的瓶子,不能看到数据,只能把数据取出来操作)
#print(len(i1))---会报错,迭代器没有长度,是竖着摆放,长度len不能计算统计个数
i2= iter([10,20,30,40])
print(i2)#<list_iterator object at 0x000001A39AF54B50>
2.获取元素
#1)获取单个元素:next(迭代器)
result = next(i1)
print(result)
print(result)
print(next(i1))
print(next(i1))
#print(next(i1)) -- 报错,迭代中iter('abc')中已经没有元素了(报错内容:StopIteration)
#不管以什么样的方式得到迭代器中元素的值,那么这个元素一定会从迭代器里消失
print(list(i2)) #[10,20,30,40]
next(i2)
print(next(i2))#报错,已经取出元素转换成列表,已从迭代器中取出所有元素
i3 = iter((10,'abc',20,False))
for x in i3:
print(x)
#print(next(i3)) --报错
print(list(i3)) #输出[]---元素已经取完所以转换成列表是空集
二、生成器
1)什么是生成器 —generator(英文名)
生成器是一种容器:也是一种特殊的迭代器,具备迭代器的特点
2)怎么创建生产器
a.调用带有yield关键字的函数就可以得到一个生成器。(只要函数里有yield就可以产生生成器)
b.调用普通函数会执行函数体并且获取函数返回值(函数调用表达式的值就是函数的返回值)
c.如果被调用的函数中有yield,那么调用函数的时候不会执行函数体,也不会获取函数返回值(),函数调用表达式的值是一个生成器对象
def func1():
print('函数')
if 10 == 20:
yield
return 100
result = func1() #调用函数先执行函数体在获取返回值
print(result) #<generator object func1 at 0x000001C8F298B9E0>
#因为函数中有yield,所以首先这是一个生成器,没有遇到yield直接返回的地址信息,生成器生成的值只与yield后面的元素有关系
3)控制生成器元素的个数和元素
原理:生成器中有多少个元素由生成器中遇到yield的次数决定,每次遇到yield后面的值是什么,那么生成器生成的值就是什么
a.调用函数创建的生成器中有多少个元素,每个元素是什么由执行完函数体会遇到几次yield以及每次遇到yield的时候其后面的数据决定
def func2():
yield 100
yield 200
yield 300
yield 400
for x in range(3):
yield 100+x
gen1 = func2()
print(gen1)
next(gen1)
#next(gen1) 当遇到一次yield(函数中只遇到一次yield)第二次调用会报错
print(list(gen1))#重新创建了一个生成器
#练习:创建一个生成器,可以创建的数据:'py001','py002','py003'..'py100'
方法一:
def func():
for x in range(1,101):
if x // 10 == 0:
yield 'py' + '00'+str(x)
elif 100> x //0 >=10:
yield 'py' + '0' + str(x)
else:
yield 'py' + str(x)
print(list(func()))
方法二:
def func1(subject):
for x in range(1,101):
yield f'{subject}{x:0>3}' #用的f-string语法,X>N--填补数值为X,长度为N
gen1 = func1('python')
print(next(gen1)) #python001
print(next(gen1)) #python002
print(next(gen1)) #python003
print(list(gen1))['python004', 'python005'...'python099', 'python100']
def func3():
print('ttttttttt')
yield 10
print('============')
yield 20
print('-------------')
yield 30
print('end')
gen1 = func3()
next(gen1) #ttttttttt 获取生成器并没有打印生成器的值所以不是10,在获取的同时函数调用会执行打印的操作
next(gen1) #============ 不会重复执行之前yield的代码
next(gen1)#-------------
#next(gen1) #会报错,但是会打印end,从上一个yield执行到最后没有遇到另一个yield所以会报错
def func4():
yield 111
yield 222
yield 333
print(next(func4())) #111
print(next(func4())) #111 每次这么调用都会产生一个新的生成器(相当于重新调用函数)
gen = func4()
print(next(gen))#111
print(next(gen))#222 #相当于用变量保存了这个生成器,在这个保存的生成器上面调用,这个不是重新创建一个生成器
练习:写一个创建一副扑克牌的生成器
def puke():
colors = '♣♠♥♦'
nums = [str(x) for x in range(2,11)] + list('JQKA')
for num in nums:
for color in colors:
yield color + num
yield '大王'
yield '小王'
gen1 = puke()
pockers = list(gen1)
form random import shuffle,choice,choices
#洗牌操作(系统自带模块,随机打乱列表中元素的顺序)
shuffle((pockers)) #将列表转换成元组
print(pockers)
#随机选择(choice随机选一张,choices随机选多张)(后面加'k='后面的数字为抽取几张)
print(choices(pockers,k=3))#随机在pockers中抽取三张牌
系统自带模块,随机打乱列表中元素的顺序)
shuffle((pockers)) #将列表转换成元组
print(pockers)
#随机选择(choice随机选一张,choices随机选多张)(后面加’k='后面的数字为抽取几张)
print(choices(pockers,k=3))#随机在pockers中抽取三张牌