python:迭代器 生成器 可迭代对象 容器
容器
容器就是一个用来存储多个元素的数据结构,常见的容器包括【列表】、【元组】、【字典】、【集合】、【字符串】
容器有两个特点:
- 容器中的元素可通过迭代获取
2. 所有容器中的元素被存储在内存中。
可迭代对象
实现了__iter__方法的对象就叫做可迭代对象。直观理解就是能用for循环进行迭代的对象就是可迭代对象。
如:字符串,列表,元祖,字典,集合等等,都是可迭代对象。
iter():将可迭代对象转为迭代器
import sys
mylist1 = [1,3,4,6,7,8,'osaiduhgfoiuydsfhguy','adsuygfydshgf','654856465',88,90,344]
print(type(mylist1))
print(len(mylist1))
print(sys.getsizeof(mylist1)) #输出list占用内存空间
myiter1= iter(mylist1) #将list转为迭代器
print(type(myiter1))
print(sys.getsizeof(myiter1)) #输出迭代器占用内存空间
》》
<class 'list'>
12
160
<class 'list_iterator'>
56
迭代器:
任何实现了__iter__() 和 __next__()方法的对象都是迭代器。
__iter__()返回迭代器自身,__next__()返回容器中的下一个值,如果容器中没有更多元素了,则抛出StopIteration异常。而且,迭代器不会一次性吧所有元素都加载到内存,而是需要的时候才返回结果。
调用next()方法的时候返回容器中的下一个值,
迭代器每次调用next()方法的时候做两件事:
- 为下一次调用next()方法修改状态。
- 生成当前调用的返回结果。
class Myiterator():
#迭代器求斐波那契数列
def __init__(self):
self.prev = 0
self.curr = 1
def __iter__(self):
return self
def __next__(self):
value = self.curr
self.curr += self.prev
self.prev = value
return value
为什么list、dict、str等数据类型不是Iterator?
这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。
使用场景
优点:省内存,不需要向列表那样存储整个数据
生成器:
生成器是一种特殊的迭代器。特殊在我们可以通过send()方法像生成器中传入数据,而迭代器只能将数据输出。生成器一定是迭代器(反之不成立)
其主要的特点有:
1、拥有yield关键字的函数就是生成器函数,生成器拥有迭代器的迭代传出数据的功能,但用关键字yield来替代迭代器中的__next__()方法来实现。
2、生成器可以传入数据(使用send())进行计算(不同于迭代器),并根据变量内容计算结果后返回。
3、迭代器不会一次把所有的元素加载到内存,而是调用的时候才生成返回结果(这点相同于迭代器)
4、可以通过for循环进行迭代(因为生成器是迭代器)
总结:生成器是一种特殊的迭代器,其具有传入数据的功能。
python两种方式提供生成器:
- 生成器函数:
- 使用yield语句而不是return语句返回结果
- yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重新在挂起的地方继续执行。函数中可以有多个yield,每个yield都会挂起一次
3.在for 循环中迭代,或使用next(iterobject,defalt)函数
- 生成器表达式:类似于列表推导式,但是,生成器返回按需要产生结果的一个队想,而不是一次构建整个结果列表
列表推导式: squares = [x**2 for x in range(5)] #squres = [0,1,4,9,16]
换成圆括号--生成器: squares = (x**2 for x in range(5))
next(squares) # 0
next(squares) # 1
使用方法
启动:生成器的启动需要用next(xx),或xx.send(None)
Send()
实际上next()和send()在一定意义上作用是相似的,区别是send()可以传递yield表达式的值进去,而next()不能传递特定的值,只能传递None进去。因此,我们可以看做c.next() 和 c.send(None) 作用是一样的。
解析:
1.第一次执行只执行到yield右侧 并返回yield右侧的值
2.send() 把参数传递给temp,并让生成器执行一次到yield右侧,接收返回值
使用场景
优点:Python使用生成器对延迟操作提供了支持.所谓延迟操作,是指在需要的时候才产生结果,而不是立即产生结果.
- 当需要创建一个包含一百万元素的列表时,使用列表定义是不现实的,列表元素可以用算法推算出来后,节省大量内存空间,适合使用生成器。
迭代器与生成器区别
- 生成器属于迭代器,但是生成器可以传参数(send()),迭代器不行
- 迭代器是一个对象,需要定义迭代器类来实例化。
- 生成器是一个对象,用带yield的函数返回
参考:
上一篇: Aspose导出word