迭代器与生成器

迭代器与生成器、生成器表达式

迭代器

迭代器:用于迭代操作,可以像列表一样迭代获取其中每一个元素,任何实现了__ next __ 方法的对象都可以称为迭代器。

与列表区别:列表一次性将所有元素都加载到内存中,而迭代器以一种延迟计算的方式返回元素,也就是一次加载一个元素。这也是迭代器的优点,加入列表中元素个数过大,可能会出现内存不足的情况,而迭代器并不是把所有元素都装载到内存中,而是当调用__ next __方法的时候才返回一个元素(按需调用)。而for循环实现原理也是不断调用迭代器的next方法。

如:

class Fib:
	def __init__(self, n):
		self.pre = 0
		self.cur = 1
		self.n = n
		
	def __iter__(self):
		return self
	
	def __next__(self):
		if self.n > 0:
			value = self.cur
			self.cur = self.cur + self.pre
			self.pre = value
			self.n -= 1
			return value
		else:
			raise StopIteration()
			
			
f = Fib(10)
# 第一种遍历方法
print([i for i in f]) # for循环实际上就是调用迭代器中的next方法

# 第二种遍历方法
print(next(f))
print(next(f))
print(next(f))
print(next(f))
print(next(f))

生成器

生成器(Python会自动实现迭代器协议):用关键字yield返回值的函数(一般函数用return关键字),这种函数叫生成器函数,函数被调用时会返回一个生成器对象,本质上还是一个迭代器,也是用在迭代操作中,因此它有和迭代器一样的特性,唯一的区别在实现方式上不一样,生成器更简洁。由于生成器自动实现了迭代器协议,所以,我们可以调用它的next方法,并且,在没有值可以返回的时候,生成器自动产生StopIteration异常。

特点:

语法上和函数类似:生成器函数和常规函数几乎是一样的。它们都是使用def语句进行定义,差别在于,生成器使用yield语句返回一个值,而常规函数使用return语句返回一个值

自动实现迭代器协议:对于生成器,Python会自动实现迭代器协议,以便应用到迭代背景中。

状态挂起:生成器使用yield语句返回一个值。yield语句挂起该生成器函数的状态,保留足够的信息,以便之后从它离开的地方继续执行。

def func(n):
    yield n ** 2

print(func(10))
print(next(func(10)))

g = func(10)
for i in g:
    print(i)

另外需要注意一点,生成器只能遍历一次。想要第二次遍历,需要重新生成。

生成器表达式

将列表推导式的中括号换成圆括号就是一个生成器表达式。

squares = [x**2 for x in range(5)] # 列表推导式
squares = (x**2 for x in range(5)) # 生成器表达式

迭代器协议是指:对象需要提供next方法,它要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代

可迭代对象就是:实现了迭代器协议的对象

协议是一种约定,可迭代对象实现迭代器协议,Python的内置工具(如for循环,sum,min,max函数等)使用迭代器协议访问对象。因此min,sum等操作也是类似于迭代器采用next方法一个一个遍历元素进行相应的操作。

Python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。例如, sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器也实现了迭代器协议。

协议访问对象的。例如, sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器也实现了迭代器协议。

注意:
关于__ iter __ 方法与 __ next __ 方法:
常识:如果一个类想被用于for ... in循环,类似list或tuple那样,就必须实现一个__iter__()方法,该方法返回一个迭代对象,然后,Python的for循环就会不断调用该迭代对象的next()方法拿到循环的下一个值。即for循环开始时,会首先进入__ iter __ 方法得到一个可迭代对象,然后调用next方法获取元素。

关于iter() 方法:iter(object[, sentinel])
使用该方法直接返回一个可迭代对象:iter 创建了一个迭代器对象,每次调用这个迭代器对象的__next__()方法时,都会调用 object, object 是支持迭代的集合对象,如list。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值