欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

python:迭代器 生成器 可迭代对象 容器

程序员文章站 2024-01-15 12:42:52
...

python:迭代器 生成器 可迭代对象 容器

容器

 

容器就是一个用来存储多个元素的数据结构,常见的容器包括【列表】、【元组】、【字典】、【集合】、【字符串】

容器有两个特点:

  1. 容器中的元素可通过迭代获取

    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()方法的时候做两件事:

  1. 为下一次调用next()方法修改状态。
  2. 生成当前调用的返回结果。
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两种方式提供生成器:

  1. 生成器函数
  1. 使用yield语句而不是return语句返回结果
  2. yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重新在挂起的地方继续执行。函数中可以有多个yield,每个yield都会挂起一次

    3.在for 循环中迭代,或使用next(iterobject,defalt)函数

python:迭代器 生成器 可迭代对象 容器

 

  1. 生成器表达式:类似于列表推导式,但是,生成器返回按需要产生结果的一个队想,而不是一次构建整个结果列表

列表推导式: 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) 作用是一样的。

python:迭代器 生成器 可迭代对象 容器

 

 

解析:

1.第一次执行只执行到yield右侧 并返回yield右侧的值

2.send() 把参数传递给temp,并让生成器执行一次到yield右侧,接收返回值

 

 

使用场景

优点:Python使用生成器对延迟操作提供了支持.所谓延迟操作,是指在需要的时候才产生结果,而不是立即产生结果.

  1. 当需要创建一个包含一百万元素的列表时,使用列表定义是不现实的,列表元素可以用算法推算出来后,节省大量内存空间,适合使用生成器。

 

迭代器与生成器区别

  1. 生成器属于迭代器,但是生成器可以传参数(send()),迭代器不行
  2. 迭代器是一个对象,需要定义迭代器类来实例化。
  3. 生成器是一个对象,用带yield的函数返回

 

 

参考:

https://www.cnblogs.com/thesong/p/10925804.html