python 生成器 迭代器 的区别

本文深入解析迭代器与生成器的概念,阐述两者之间的区别与联系,介绍如何使用Python的iter()函数将可迭代对象转换为迭代器,以及生成器的创建方式和访问元素的不同方法,对比列表推导式与生成器推导式在时间和内存开销上的差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

1)可迭代对象包含迭代器。

2)如果一个对象拥有__iter__方法,其是可迭代对象;如果一个对象拥有next方法,其是迭代器。

3)定义可迭代对象,必须实现__iter__方法;定义迭代器,必须实现__iter__和next方法。

4)具备可迭代性,那么就可以直接用for循环

问题1:具备可迭代性的元素,就一定是迭代器吗?

答案:不一定 验证如下:

from collections import Iterator
list = [1,2,3]

if isinstance(list,Iterator):
    print("list是迭代器")
    print(next(list))
else:
    print("list不是迭代器")

运行结果为:

list不是迭代器

由此得出:列表具有可迭代性,但是列表不是迭代器

问题2:如何让具有迭代性的元素变成迭代器?

答案:使用iter()函数

iter()函数会返回一个定义了 next()方法的迭代器对象,它在容器中逐个访问容器内元素,next()
也是 python 的内置函数。在没有后续元素时,next()会抛出一个 StopIteration 异常


list1 = [2,4,6]
list2 = iter(list1)
print(type(list2))  # 打印对象的类型
print(dir(list2))  # 打印对象的内置方法
print(next(list2))
print(next(list2))
print(next(list2))
print(next(list2))

运行结果如下:
<class 'list_iterator'>
  File "F:/python_project/Django_project/captcha/delete.py", line 8, in <module>
    print(next(list2))
StopIteration
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__length_hint__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__']
2
4
6

问题3:什么是迭代器?

能被next()函数访问,并不断返回下一个值的对象

问题4:什么是生成器?

生成器是一种特殊的迭代器,生成器自动实现了“迭代器协议”(即__iter__和next方法),不需要再手动实现两方法。

1,什么是生成器?
		genterator,记录一个算法,可以一边循环一边计算的一种机制

2,列表推导式
		更加耗时,更加开销系统内存

3,存储数据
		实际上算法的存储

4,节约时间,节省内存开销

列表推导式的时间开销验证如下:

import time   		   # 时间模块
import sys     		   # 系统模块 可以计算变量在内存中所使用的内存开销 需要用到固定的方法去计算
time.clock()
list = [x for x in range(2, 1000000, 2)]
costTime = time.clock()
print("创建列表耗时%g" % costTime)
print("创建列表内存开销%d" % sys.getsizeof(list))

运行结果为:

创建列表耗时0.0590449
创建列表内存开销4290016

生成器推导式的时间开销验证如下:

import time     # 时间模块
import sys      # 系统模块 可以计算变量在内存中所使用的内存开销 需要用到固定的方法去计算
time.clock()

list = (x for x in range(2, 1000000, 2))
costTime = time.clock()
print("创建生成器耗时%g" % costTime)
print("创建生成器内存开销%d" % sys.getsizeof(list))

运行结果为:

创建列表耗时1.2402e-05
创建列表内存开销88

**

2,访问生成器元素的方式

**

生成器里面访问元素的第一种方式:for循环遍历

list = (x for x in range(2, 10, 2))
for i in list:
    print(i)

运行结果为:

2
4
6
8

访问生成器中的元素的第二种方式:使用next方法访问

list = (x for x in range(2, 10, 2))
print(next(list))
print(next(list))
print(next(list))  # 需要注意的是:超出生成器生成数据的范围,会报错StopIteration

访问生成器中的元素的第三种方式:使用__next__方法访问

list = (x for x in range(2, 10, 2))
print(list.__next__())
print(list.__next__())
print(list.__next__())

运行结果为:

2
4
6

访问生成器中的元素的第四种方式:使用send()方法访问

list = (x for x in range(2, 10, 2))
print(list.send(None))     			 #注意: 对第一个参数有要求必须给None参数,后续的参数可以随便给
print(list.send("abc"))
print(list.send("efg"))

运行结果为:

2
4
6

**

3,创建生成器的方式

**
方式1:

	(x for x in range(10))   # 外面的是 () 小括号它就是一个生成器  外面是 [] 中括号它就是一个列表推导式

方式2:yield 用在函数中

def test():
    for x in range(5):
        yield x

f = test()
print(type(f))
print(next(f))
print(next(f))

运行结果为:

<class 'generator'>
0
1

带yield的函数是一个生成器,而不是一个函数了,这个生成器有一个函数就是next函数,
next就相当于“下一步”生成哪个数,这一次的next开始的地方是接着上一次的next停止的地方执行的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值