Python笔记-----迭代器、生成器

迭代器

1.什么叫迭代?
使用for循环遍历取值的过程,叫做迭代

2.什么是可迭代对象?
能够使用for遍历取值的对象,叫可迭代对象
可迭代对象:str、list、set、tuple 、dict
不可迭代对象: int 、float、class

3.什么是迭代器?
迭代器是一个可以记住遍历的位置的对象
①迭代器对象从集合的第一个元素开始访问,直到所有元素被访问完
②迭代器只能往前不会后退

4.如何判断一个对象是不是可迭代对象、迭代器?

from collections import Iterable
from collections import Iterator
isinstance( obj, Iterable ) #obj是不是可迭代对象
isinstance( obj, Iterator) #判断obj是不是迭代器?


一个实现了iter方法的对象是可迭代的,一个实现next方法并且是可迭代的对象是迭代器。
可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator

5.如何创建迭代器
方法一:直接在可迭代对象(字符串,列表或元组对象)上创建迭代器
方法二:把一个类作为一个迭代器使用, 需要在类中实现两个方法 iter() 与 next() .
①__iter__() 方法:返回一个特殊的迭代器对象, 这个迭代器对象实现了 next() 方法并通过 StopIteration 异常标识迭代的完成。
②__next__() 方法:(Python 2 里是 next())会返回下一个迭代器对象。

用法
#1. 创建迭代器 ,iter()函数
通过iter()函数创建可迭代对象(比如:列表、元组、字符串)的迭代器.(字符串,列表或元组对象都可用于创建迭代器)

#2. 遍历取值
迭代器对象可以使用常规 for 语句进行遍历,
也可以使用next()函数来取值。iter()函数实际上就是调用了可迭代对象的 __iter__ 方法

生成器

1. 什么是生成器?
生成器是一种特殊的迭代器(一个没有__iter__和__next__方法的特殊迭代器),不存储数据,存储生成数据的方式

2.为什么需要引入生成器?
当需要生成好多数据时,如果一下全部产生,将会占用好多内存。
eg:
创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了.
此时引入生成器,需要多少生成多少,什么时候需要什么时候继续,而不用一下子全部产生。

3.生成器特点(节省空间,暂停程序,需要时再继续执行):
①一个没有__iter__和__next__方法的特殊迭代器;
②函数只执行一部分就返回;
③可以让一个函数暂停执行,并且保存上次的值,根据上次的值恢复到原来的样子,再做接下来的操作;
④迭代器节省空间,实现循环;
⑤生成器可以让一个看起来像函数的代码暂停执行,并根据自己的想法调用next/send继续执行;

4.生成器的2种构建方式

1.将列表推导式的小括号换成中括号;

2.函数中使用yield

# 创建生成器模板
 一个函数中yield,此时这个函数不再是函数,而是生成器的模板
#创建生成器对象
当调用一个函数时,发现该函数中有yield,那么不再事调用函数,而是创建一个生成器对象

5.生成器执行流程
当第一次调用for/next执行时,会从生成器的第一行开始依次向下执行,直到在循环中碰见yield,就会返回yield后面的变量/字符;
然后第二次调用for/next时,就会从上次的yield后面的代码继续执行,直到在循环中再次碰到yield,返回;依次往下,直到没有了数据。

6.生成器、函数执行流程的区别
函数是顺序执行,遇到return语句或者最后一行函数语句就返回。
而generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

7.生成器启动方式
①可以使用 for i in 生成器对象 来遍历生成器中的数据,__ next__
②也可以用 next(生成器对象) 来一个一个获取生成器中的值(调用next()运行生成器,并 返回yield的值);
③通过send()来启动生成器,取里生成器里面的值(即返回yield的值)如下代码
注意:一般 生成器对象.send(None) 不会放到第一次启动生成器,如果非要这么做,要传入None

使用yield完成斐波那契数列
def Fibonacci(n):
	a, b = 0, 1
	count_num = 0
	while count_num < n:
	# 如果函数中有一个yield语句,那么这个就不再是函数,而是一个生成器的模板
		yield a
		a, b = b, a+b
		count_num += 1

# 如果在调用时发现这个函数中有yield,那么此时,不是调用函数,而是创建一个生成器对象
fb = Fibonacci(5)

print("使用for循环遍历生成器中的所有数字".center(40, "-"))
for i in fb:
	print(i)

print("使用next依次生成三次数字".center(40, "-"))
print(next(fb))
print(next(fb))
print(next(fb))

send()启动生成器

def Fibonacci(n):
	a, b = 0, 1
	count_num = 0
	while count_num < n:
		ret = yield a
		print("ret:", ret)
		a, b = b, a+b
		count_num += 1
	
fb = Fibonacci(5)
print(next(fb))
#send的参数会传给 yield a ,当做yield a的结果,并赋值给ret
#send的结果是 :下次调用 yield时,yield后面a的值
print(fb.send("haha"))
print(next(fb))

# 0
# ret: haha
# 1
# ret: None
# 1
(我们可以理解为,第一次使用next,先执行等号右边的代码,就将yield a返回给了next(fb);
然后下次调用send时,执行等号左边的,将send的传值赋值给ret,再执行后续代码;
或者我们可以理解 ret = yield a 为两步
===>1.yield a;
2.ret = arg;其中的arg表示send的传值,如果不传值,默认为None,所以当next在send后面调用时,就默认传了None)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值