迭代器

迭代,是访问集合内元素的一种方式。要理解迭代器,首先要理解可迭代对象,所谓可迭代对象,通俗的 说就是可以被for循环遍历的对象就是可迭代对象

任何内置了iter方法的,都是可迭代的对象,例如,listsetdicttuple等都是可迭代对象

迭代的概念

相信大家都玩过游戏,每一次游戏更新迭代,都是新增了一些功能,调整了什么,迭代就是这个概念,在python中,上一次输出的结果为下一次输入的初始值,重复的过程就称为迭代。

就好像我们游戏更新一样,都是继上一次的版本为初始的情况下,增加一些新的东西,同理,每次迭代的结果是下一次迭代的初始值。

那么,问题来了,为什么要有迭代器,因为,对于没有索引的数据类型,必须提供一种不依赖索引的迭代方式,这个方式就是迭代器。

迭代器定义

迭代器,就是可迭代对象执行iter方法,得到的结果就是迭代器,迭代器对象有next方法。它是一个状态的对象,它能在你调用你next()方法的时候返回容器中的下一个值,如果容器中没有更多的元素了,则会抛出StopIteration(停止迭代异常)

我们常用的for循环,其实它的本质就是:

  1. 利用iter函数得到函数
  2. 利用next函数依次取值
  3. 捕获异常

手写一个迭代器

class Csmt:

	def __init__(self):
		# 初始化可迭代对象和num
		self.name = []
		self.num = 0

	def add(self,na):
		# 添加元素
		self.name.append(na)

	def __iter__(self):
		# 调用iter方法,返回自身
		return self

	def __next__(self):
		# 如果 num小于name的长度
		if self.num < len(self.name):
			# 从0开始,取出可迭代对象中的元素
			ret = self.name[self.num]
			# 同时,往后移一位
			self.num += 1
			# 返回
			return ret
		else:
		# 没有元素,抛出异常
			raise StopIteration

c = Csmt()
c.add('AAA')
c.add('BBB')
c.add('CCC')
for i in c:
	print(i)

生成器

生成器是一个特殊的迭代器,它的实现更简单,yield,就是生成器实现next()方法的关键,它作为生成器执行的暂停恢复点,可以对yield表达式进行赋值,也可以将yield表达式的值返回

也就是说,yield是一个语法糖,内部实现了支持迭代器协议,同时yield内部是一个状态机,维护着挂起和继续的状态

也就是说,一边循环,一边计算的机制,就是生成器。

为什么要有生成器

假如你有一个海量的列表,你要读取中间的某些元素,那后面的绝大多数元素占用的空间都白白浪费了,如果使用生成器,在得到你需要的数据之后就停止,就没有必要创建完整的list,从而节省大量的空间。

生成器如何定义

第一种方式

  • 在函数中添加yield关键字,这个函数就是生成器

第二种方式

  • 将列表推导式的[ ] 变成 ( )

获取生成器的数据

  1. 利用for循环获取迭代器数据
  2. 利用while和异常捕获
  3. 利用list、tuple类型转换

生成器唤醒方式

由于生成器是函数暂停执行实现的,那么,我们唤醒生成器就需要使用next()来取值

或者使用__next__魔法方法

还可以使用send()函数,它可以将数据作为参数传递到生成器内部,需要注意的一点是,send不能作为第一次唤醒时使用

实现生成器

a = (i for i in range(1,11))
print(a)
for i in a:
	print(i)
'''
<generator object <genexpr> at 0x000001BEBA62E448>
1,2,3,4,5,6,7,8,9,10
'''

好啦,分享到此结束