python生成器和迭代器

本文详细介绍了Python中的迭代器和生成器概念,包括它们的定义、作用、创建方式及区别。通过实例展示了如何使用迭代器进行遍历,以及生成器如何节省内存并提供延迟操作的优势。

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

                                     Python3迭代器和生成器

 很多朋友在初次接触 python 的 迭代器 和 生成器 时,总是不理解 生成器 和 迭代器的作用 和它们之间的关系,今天笔者来详细的讲解一下。


知识点目录:

一、迭代器

1.什么是迭代器

2.举例说明

3.StopIteration 异常的作用

4.举例说明 StopIteration 的作用

二、生成器

1.什么是生成器

2.生成器的优点

3.创建生成器的方式

4.生成器的两种方法

三、生成器 和 迭代器 的区别


一、迭代器

1.什么是迭代器

迭代是访问集合元素的一种方式,迭代器是一种可以记住遍历位置的对象。迭代器只能往前不能后退。

迭代器是可以被 next()函数调用并返回下一个值的对象

迭代器中,重点关注两种方法:

__iter__ 方法:返回一个迭代器对象,可以通过 python 内建函数 iter()调用。这个迭代器对象实现了 __next__ 方法,并通过 StopIteration 异常标识迭代的完成

__next__ 方法:返回下一个迭代器对象,可以通过 python 内建函数 next()调用。


2.举例说明

# 元组可迭代数据类型
i = iter((1,2,3))    # 调用 iter()方法,获得迭代器对象

print(type(i))    # 打印数据类型
print(next(i))
print(next(i))    # 调用 next()方法,获得下一个迭代器对象
print(next(i))
print(next(i))

# 结果
<class 'tuple_iterator'>
1
2
3

# 异常:
Traceback (most recent call last):
  File "D:/Pycharm Perject save path/python/CeShi.py", line 19, in <module>
    print(next(i))
StopIteration

# 异常原因:
元组内的元素一共是 3 个,而我调用了 4 次 next()方法,每次都会返回一个元素,
当没有元素可以返回的时候,就会自动抛出异常 StopIteration 。

一般情况下,我们使用 for 循环来遍历 数据,这样可以避免因为异常而停止程序运行。

3.StopIteration 异常的作用

StopIteration 异常 用来标记迭代的完成,防止出现无限循环的情况。当重写 迭代器类 时,我们可以在 __next__() 方法中设置当完成指定循环次数后,触发 StopIteration 异常来结束迭代。 

4.举例说明 StopIteration 异常的作用

# 举例说明 StopIteration 的作用
class MyNumbers:
    def __iter__(self):
        self.a = 1
        return self

    def __next__(self):
        if self.a <= 4:
            x = self.a
            self.a += 1
            return x
        else:
            raise StopIteration    # raise 语句来触发一个异常(抛出异常)


myclass = MyNumbers()
myiter = iter(myclass)

for x in myiter:
    print(x)

# 结果
1
2
3
4

 


二、生成器

1.什么是生成器

在 python 中,使用了 yield 关键字的函数被称为 生成器(generator)。

和普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单的理解 生成器就是一个迭代器

在调用生成器运行的过程中,每次遇到yield关键字 函数都会暂停运行并保存当前的所有运行信息,然后返回 yield关键字 的值,并在下一次执行 next()方法时从当前位置继续执行

调用一个生成器,返回的是一个迭代器对象。


2.生成器的优点

1.节约内存,python 在使用生成器时对延迟操作提供了支持。所谓延迟,是指在需要的时候才产生结果,而不是立即产生结果。比如在大数据中,会使用生成器来调取数据结果而不是列表来处理数据,因为使用生成器可以 节省内存

2.迭代到下一次的调用时,所使用的参数都是第一次所保留的

3.创建生成器的方式

1.生成器表达式

类似于 列表推导式,将列表推导式的中括号,替换成圆括号,就是一个生成器表达式,但是生成器每次返回的结果只有一个,而不是一次构建一整个结果列表。 

例子:

# 列表推导式
data = [i ** 2 for i in range(5)]
print(type(data))
print(data)

# 结果
<class 'list'>
[0, 1, 4, 9, 16]



# 生成器表达式
data = (i ** 2 for i in range(5))
print(type(data))

for i in data:    # 使用for循环遍历 data 
    print(i)

# print(type(data))
# print(next(data))
# print(next(data))
# print(next(data))
# print(next(data))
# print(next(data))
# print(next(data))    # 获取第6次抛出 StopIteration 异常,使用 for 循环即可。

# 结果
<class 'generator'>
0
1
4
9
16

2.生成器函数

生成器函数 和 常规函数定义差不多,但是使用 yield关键字 来返回结果,而不是 return。yield 关键字每次会返回一个结果,然后将程序的运行状态挂起,以便下一次从它离开的地方继续执行。

例子:

# 生成器函数
def odd():
    n = 1
    while True:
        yield n
        n += 2


odd_num = odd()  # 调用生成器函数
count = 0
for o in odd_num:  # 从生成器函数中,遍历循环数据
    if count >= 5:
        break
    print(o)  # 打印遍历出来的数据
    count += 1

# 结果
1
3
5
7
9

上面的生成器函数的例子中,关键字 yield 是必备的。当一个普通函数中包含 yield 关键字时,系统会默认为是一个 generator(生成器)。


4.生成器的两种方法

生成器的两种方法 __next__() 和 send()方法。

__next__()方法 和 next()方法的作用是一样的。

send()方法向生成器函数中传入数据

4.1 __next__()方法

# next() 方法示例
def odd():
    n=1
    while True:
        yield n
        n+=2
odd_num=odd()

for i in range(4):
    print(next(odd_num))


# __next__() 方法示例
def odd():
    n=1
    while True:
        yield n
        n+=2
odd_num=odd()

for i in range(4):
    print(odd_num.__next__())



# 结果
1
3
5
7
1
3
5
7

从上面的程序中可以看出,next(odd_num)    odd_num.__next__() 的作用是一样的。

4.2 send()

# send()方法示例
def fib(times):
    n = 0
    a, b = 0, 1
    while n < times:
        temp = yield b  # 在 yield 前面添加一个变量
        print(temp)
        a, b = b, a + b
        n += 1


f = fib(5)
print(f.__next__()) # 调用 __next__ 打印值
print(f.send("Super Man 超人"))   # 使用send()方法传入值
print(f.send("lron Man 钢铁侠"))

# 结果
1
Super Man 超人
1
lron Man 钢铁侠
2

从上面的示例中可以看到,使用 send()方法时,必须在 yield 关键字前面添加一个变量,并打印这个变量。但是强调一点,在使用send()方法之前,必须要先使用至少一次 __next__ 方法,因为生成器不可以在使用之前导入任何非None的参数。由此可以知道,send()是用来向生成器中导入参数并返回该参数的,与该参数一起返回的还有生成器中原先保存的数据。


三、生成器 和 迭代器 的区别

生成器能够做到迭代器能做的所有事情,而且因为生成器自动创建了 iter()和 next()方法,所以会显得更加简洁一些,同时生成器相对更加高效,使用 生成器 表达式 取代 列表解析 可以节省内存。除了 创建 和 保存程序状态 的自动方法,当没有 yield 可以返回的值时,自动抛出 StopIteration 异常。


非常感谢同仁的观看.如果小编写的有问题,欢迎评论.发现问题后会第一时间修改.

祝大家工作学习顺利.    ♥(ˆ◡ˆԅ)  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值