python全栈学习记录(十四)迭代器和生成器

迭代器和生成器

一、迭代器

迭代器即迭代取值的工具,迭代是一个重复的过程,每一次重复都是基于上一次的结果而来,迭代的目的通常是为了取得某一想要的结果。

基于索引的迭代器取值方式只适用于列表、元组、字符串类型,而对于没有索引的字典、集合、文件则不在适用。所以必须找到一种通用的并且不依赖于索引的迭代器取值方式:迭代器。

1.可迭代对象

在python中但凡内置有__iter__方法的对象都是可迭代的对象,如字符串、列表、元组、字典、集合、文件等都是可迭代的对象。

a='123'
print(a.__iter__())
b=[1,2,3]
print(b.__iter__())
<<< <str_iterator object at 0x000002A5C9726FD0>
<<< <list_iterator object at 0x000002A5C9726FD0>

2.迭代器

迭代器指的是既内置有__iter__方法,又内置有__next__方法的对象。执行可迭代对象的__iter__方法得到的就是内置的迭代器对象,文件句柄本身就是迭代器。

迭代器对象一定是可迭代对象,而可迭代对象则不一定是迭代器。

执行迭代器对象的__next__方法可以取出迭代器中的一个值,当迭代器中值取完以后再执行__next__方法会报StopIteration。迭代器是python提供的一种不通过索引取值的方法,只要存在多个值,无论是否是序列类型都可以通过迭代器的方式取值。

a={1,2,3}
a=a.__iter__()
print(a.__next__())
print(a.__next__())
print(a.__next__())
print(a.__next__())
<<<1
<<<2
<<<3
<<<StopIteration

3.for语句的基本原理

为什么可迭代对象变成迭代器以后,内部还有__iter__方法呢?迭代器的__iter__方法是为了符合for语句原理而存在的,for语句工作时每次都会调用到对象的__iter__方法。
for语句执行的步骤:

  1. 调用__iter__方法转遍历对象为迭代器(迭代器调用__iter__以后还是迭代器)
  2. 调用__next__方法取迭代器的值
  3. 循环以上步骤
  4. 迭代器取完值退出

用while循环模拟for循环遍历可迭代对象/迭代器:

g=[1,2,3]
g=g.__iter__()
while True:
	try:#try语句会在报错时跳转到ecept语句
		print(g.__next__())
	except StopIteration:
		break
<<<1
<<<2
<<<3

4.迭代器的优缺点

优点:

  • 提供了一种通用的、可以不依赖索引的迭代取值方式
  • 迭代器对象更加节省内存(迭代器是每取一个值才把取的值读入内存中)

缺点:

  • 迭代器的取值不如按照索引的方式更灵活,因为它只能往后取不能往前退
  • 无法预测迭代器值的个数

二、生成器

在函数内但凡出现yield关键字,再调用函数就不会执行函数体代码,会返回值一个值,该值称之为生成器生成器,本质就是迭代器。

1.生成器的使用方式

生成器是一种自定义迭代器的方式。

def add(x):
    while x<3:
        x+=1
        yield x

g=add(1)#g为生成器对象
print(g.__iter__)
print(g.__next__())#add执行到yield处返回x的值并停滞
print(g.__next__())
print(g.__next__())#x=3不满足循环条件,循环结束,函数中没有yield报StopIteration
<<< <method-wrapper '__iter__' of generator object at 0x000001D0F38D69E0>
<<<2
<<<3
<<<StopIteration

用for遍历生成器:

def add(x):
    while x<5:
        x+=1
        yield x

for i in add(1):
	print(i)
<<<2
<<<3
<<<4
<<<5

2.yield关键字

yield关键字可以给函数内部的变量传值:

def eater():
	print('preparing now')
	while True:
		food=yield
		print(food)

g=eater()
g.__next__()#给food传值前必须先使用__next__方法让生成器运行至yield处
g.send('花生')
g.__next__()#相当于g.send(None)
<<<preparing now
<<<花生
<<<None

yield也可以同时赋值返回值

def eater():
	food_list=[]
	print('preparing now')
	while True:
		food=yield food_list
		food.append(food)

def eater():
	food_list=[]
	print('preparing now')
	while True:
		food=yield food_list
		food_list.append(food)

g=eater()
print(g.__next__())
print(g.send('花生'))
print(g.send('土豆'))
<<<preparing now
<<<[]
<<<['花生']
<<<['花生', '土豆']

3.三元表达式与多种生成式

三元表达式:
res=条件成立时的返回值 if 条件 else 条件不成立时的返回值

x,y=10,20
res=x if x>y else y
res
<<<20

列表生成式:
[res for item1 in iterable1 if condition1
for item2 in iterable2 if condition2

]

#生成存放1到10的列表
[i for i in range(1,11)]
<<<[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

生成器生成式:
(res for item1 in iterable1 if condition1)

(i for i in range(1,11))
<<<<generator object <genexpr> at 0x00000274534CD430>

字典生成式:
{k:v for item1,item2 in iterable1 if condition1}

{k: v for k,v in enumerate(range(5,10))}
<<<{0: 5, 1: 6, 2: 7, 3: 8, 4: 9}

集合生成式:
{ res for item1 in iterable1 if condition1}

{i for i in range(1, 11)}
<<<{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值