python生成器和迭代器

面经:
问:python生成器和迭代器有什么区别??
答: python迭代器有两个特定的方法,1.iter()用来生成迭代器 2.next() 用来迭代器的取值-----把一个字符串、字典变成迭代器的方法就是先iter(dict), 再通过next(dict)就可以不断的得到需要的对象。
2、生成器是一种特殊的迭代器,支持所有的迭代器操作,还有就是生成器还实现了普通迭代器没有的特点 比如:可以使用send()方法和迭代器内部进行数据交互,和 包含yield关键字 ,其次还能使用close方法进行关闭,可以使用throw方法引发内部异常。
创建生成器的两种方式:

1(x for x in range(10))
2def odd():
    yield 1
    yield 2
    yield 3

总结:正常使用的range函数、列表、元组、字符串、字典和集合都是可迭代的,包含__iter__,但是不可next(),所以使用iter()之后,便可以使用next(),便成为迭代器。

生成器是特殊的迭代器,自动可以next()。
在这里插入图片描述
合理使用生成器,能够有效提高代码可读性
生成器的唯一注意事项就是:生成器只能遍历一次

参考

通过实现迭代器协议对应的__iter__()和next()方法,可以自定义迭代器类型。对于可迭代对象,for语句可以通过iter()方法获取迭代器,并且通过next()方法获得容器的下一个元素。
生成器是一种特殊的迭代器,内部支持了生成器协议,不需要明确定义__iter__()和next()方法。
生成器通过生成器函数产生,生成器函数可以通过常规的def语句来定义,但是不用return返回,而是用yield一次返回一个结果。

生成器(迭代器的特殊情况)

在这里插入图片描述

[x for x in range(10)]  #列表的生成式语法来创建列表容器, 不是生成器~~
#[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
#用这种语法创建列表之后元素已经准备就绪所以需要耗费较多的内存空间
(x for x in range(10)) #不是一个列表,而是一个生成器对象
#<generator object <genexpr> at 0x106c6d930>
# 通过生成器可以获取到数据但它不占用额外的空间存储数据
# 每次需要数据的时候就通过内部的运算得到数据(需要花费额外的时间)

生成器语法,比较耗费内存空间。(x for x in range(10))

生成器函数与普通函数的区别在于:当调用内置函数next()或使用for-in语句迭代时执行完yield语句就会将生成器函数挂起,下次会从挂起的地方继续执行。感觉生成器函数还挺不错的~~

def odd():
    yield 1
    yield 2
    yield 3
    
o=odd()  
print(o)  #<generator object odd at 0x106c6d8b8>
print(next(o))  #1
print(next(o))  #2
print(next(o))   #3
print(next(o)) ### 报错

yield相当于return,直接输出o并不能输出元素,要使用next()。

迭代器

可迭代对象 = 通过Itearable判断

区分可迭代对象和迭代器对象,二者并不相同
可以用于for-in语句的对象被称为可迭代对象(Iterable)对象。
可以调用内置函数isinstance()判断一个对象是否是可迭代对象。标准库模块collection中的类Iterable用于表示可迭代对象。

from collections import Iterable
print(isinstance([2,4,6, 8, 10], Iterable))   #True
print(isinstance('abc', Iterable))   #True
print(isinstance((x for x in range(10)), Iterable))   #True


列表、字符串、生成器都是可迭代对象(isinstance函数结果返回True),实际上,range函数、列表、元组、字符串、字典和集合,生成器等都是可迭代对象,都可以用于for-in语句。

迭代器对象 == 可通过Iterator判断

如果一个可迭代对象可以作为内置函数**next()**的实参从而支持惰性推算,那么该对象被称为迭代器(Iterator)对象。
对于range、列表、元组、字符串。字典和集合等可迭代对象,都不可作为内置函数next()的实参,而生成器可以。所以,生成器是迭代器的一种。

list = [2,4,6, 8, 10]
next(list)
#TypeError: 'list' object is not an iterator

string = 'abc'
next(string)
#TypeError: 'str' object is not an iterator

gen=(x for x in range(10))
next(gen)  #0

from collections import Iterator
print(isinstance(list, Iterator))  #False
print(isinstance(string, Iterator))   #False
print(isinstance((x for x in range(10)), Iterator))  #True

可迭代对象可以调用内置函数iter()把不支持惰性推算的可迭代对象转换为迭代器对象。

iter_l = iter(list)
iter_s = iter(string)

print(isinstance(iter_l, Iterator))   #True
print(isinstance(iter_s, Iterator))   #True

print(next(iter_l))   #2
print(next(iter_l))   #4
print(next(iter_l))   #6
print(next(iter_l))   #8
print(next(iter_l))   #10
print(next(iter_l))   #StopIteration
#当容器中没有可访问的元素后,next()方法将会抛出一个StopIteration异常终止迭代器。

print(next(iter_s))   #a
print(next(iter_s))   #b
print(next(iter_s))   #c
print(next(iter_s))   #StopIteration

如果一个对象同时实现了特殊方法__iter__()和___next__(),那么该对象也被称为迭代器对象。如果将该对象用于for-in语句首先会调用特殊方法__iter__()返回一个可迭代对象,然后不断调用该可迭代对象的特殊方法__next__()返回下一次迭代的值,知道遇到StopIteration时退出循环。

总结

如果想要for-in语句可以用于自定义对象的实例对象,必须在自定义类对象中实现特殊方法__iter__()和__next__()。for-in语句首先会调用特殊方法__iter__()返回一个可迭代对象,然后不断调用可迭代对象的特殊方法__next__()返回下一次迭代的值,直到遇到StopIteration时退出循环。
只实现了特殊方法__iter__()的类对象,被称为可迭代对象;同时实现了特殊方法__iter__()和__next__()的类对象,被称为迭代器类对象。
之所以for-in语句可以用于某些内置类对象(例如:list、tuple、str等)的实例对象,是因为这些内置类对象中都同时实现了特殊方法__iter__)和__next__()。
通过实现迭代器协议对应的__iter__()和next()方法,可以自定义迭代器类型。对于可迭代对象,for语句可以通过iter()方法获取迭代器,并且通过next()方法获得容器的下一个元素。
生成器是一种特殊的迭代器,内部支持了生成器协议,不需要明确定义__iter__()和next()方法。
生成器通过生成器函数产生,生成器函数可以通过常规的def语句来定义,但是不用return返回,而是用yield一次返回一个结果。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值