(7)100天python从入门到拿捏《迭代器和生成器》

部署运行你感兴趣的模型镜像

迭代器和生成器

在 Python 中,迭代器生成器是非常重要的概念。它们使得 Python 的循环结构更加简洁高效,尤其在处理大量数据时,它们可以大大减少内存的消耗。下面我会详细介绍迭代器和生成器的定义、用法、以及它们的区别和关系。

1. 迭代器

定义

迭代器是一个对象,它实现了 __iter__()__next__() 方法,使得对象可以在循环中逐个返回其元素。迭代器用于遍历一个集合数据,比如列表、元组、字典等。

特点
  • 迭代器在内存中逐个生成元素,不会一次性将所有数据存储在内存中。
  • 迭代器只能向前遍历,不能倒回。
  • 迭代器提供了 惰性求值,即只有在需要时才会生成下一个元素。
迭代器的工作原理
  1. 通过 __iter__() 方法返回迭代器对象本身。
  2. 通过 __next__() 方法返回下一个元素。
  3. 当没有元素时,__next__() 会引发 StopIteration 异常。
创建迭代器

可以通过可迭代对象的 iter() 函数将其转换为迭代器。

# 创建一个迭代器
my_list = [1, 2, 3]
iterator = iter(my_list)

print(next(iterator))  # 输出:1
print(next(iterator))  # 输出:2
print(next(iterator))  # 输出:3
# 如果再次调用next(),将抛出 StopIteration 异常
# print(next(iterator))  # StopIteration
自定义迭代器

可以通过定义一个类,并实现 __iter__()__next__() 方法来创建自己的迭代器。

class MyIterator:
    def __init__(self, start, end):
        self.current = start
        self.end = end
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.current >= self.end:
            raise StopIteration
        self.current += 1
        return self.current - 1

# 使用自定义的迭代器
iterator = MyIterator(1, 4)
for value in iterator:
    print(value)

输出

1
2
3

2. 生成器

定义

生成器是一个特殊类型的迭代器。它是通过 yield 关键字定义的函数(也叫生成器函数)。与普通函数不同,生成器函数在执行时会暂停并记住当前位置,直到下次调用生成器时再继续执行。

特点
  • 生成器使用了 惰性求值,在需要时才生成一个元素,因此它们是高效的内存利用方式。
  • 生成器函数通过 yield 语句逐个返回数据,每次调用 next() 都会继续从上次停止的地方开始。
  • 生成器会自动实现迭代器的协议,因此可以像迭代器一样使用 for 循环进行遍历。
创建生成器

生成器是通过带有 yield 的函数定义出来的。每当 yield 被执行时,函数暂停并返回一个值,之后可以通过调用 next() 恢复执行并返回下一个值。

def my_generator():
    yield 1
    yield 2
    yield 3

gen = my_generator()
print(next(gen))  # 输出:1
print(next(gen))  # 输出:2
print(next(gen))  # 输出:3
# 如果再次调用next(),将抛出 StopIteration 异常
# print(next(gen))  # StopIteration
使用 for 循环遍历生成器
for value in my_generator():
    print(value)

输出

1
2
3

3. 生成器表达式

生成器表达式是一种简洁的生成器定义方式,它类似于列表推导式,但返回的是生成器对象而不是一个列表。

语法:

(expression for item in iterable if condition)

案例

gen_exp = (x ** 2 for x in range(5))
print(next(gen_exp))  # 输出:0
print(next(gen_exp))  # 输出:1
print(next(gen_exp))  # 输出:4

4. 迭代器与生成器的区别

特性迭代器 (Iterator)生成器 (Generator)
定义方式通过实现 __iter__()__next__() 方法定义通过 yield 关键字或生成器表达式定义
内存管理一次性将所有元素加载到内存中按需生成元素,内存占用低
实现复杂度需要定义 __iter__()__next__() 方法通过函数和 yield 关键字实现,代码更简洁
惰性求值
用法手动实现迭代器协议更加简洁和直观,适用于生成大量数据
是否能迭代
是否可以重新迭代不能重新开始迭代(除非重新创建迭代器对象)不能重新开始迭代(除非重新创建生成器对象)

5. 生成器的性能优势

生成器的主要优势是 内存效率。它们在每次迭代时生成一个值,并将其返回,而不是一次性将所有数据加载到内存中。这在处理大量数据时尤为重要,特别是当数据量非常大,甚至超出内存容量时,生成器提供了一个很好的解决方案。

生成大量数据时的内存优势

当你要处理一个包含 10 亿数字的列表,如果使用普通列表,你的程序可能会因为内存不足而崩溃。而使用生成器,你的程序只会按需生成每个元素,不会占用太多内存。

def large_data_generator():
    for i in range(1000000000):
        yield i

# 这个生成器不会一次性将所有 10 亿个数字存储在内存中
gen = large_data_generator()

6. 生成器的 Send()Close() 方法

生成器不仅仅能使用 yield 来生成值,还支持 send()close() 方法,用于向生成器传递数据或关闭生成器。

send() 方法

send() 方法用于向生成器传递值并恢复生成器的执行,生成器会执行到下一个 yield 语句,并将该值返回。

案例

def generator():
    result = yield 1  # 暂停并返回 1
    yield result  # 返回通过 send() 传入的值

gen = generator()
print(next(gen))  # 输出:1
print(gen.send(10))  # 输出:10
close() 方法

close() 方法用于关闭生成器,停止生成器的执行。

案例

def generator():
    yield 1
    yield 2

gen = generator()
print(next(gen))  # 输出:1
gen.close()  # 关闭生成器

总结

  • 迭代器 是一种可以用于遍历的对象,通过实现 __iter__()__next__() 方法来定义。
  • 生成器 是一种特殊类型的迭代器,通过使用 yield 关键字定义,具备惰性求值的特点,更加节省内存。
  • 生成器表达式 是一种更简洁的定义生成器的方式,类似于列表推导式,但返回的是生成器。
  • 生成器的 内存优势 在于它们只在需要时生成数据,而不一次性加载所有数据,这使得它们特别适合处理大量数据。

python学习专栏导航
(1)100天python从入门到拿捏《Python 3简介》
(2)100天python从入门到拿捏《python应用前景》
(3)100天python从入门到拿捏《数据类型》
(4)100天python从入门到拿捏《运算符》
(5)100天python从入门到拿捏《流程控制语句》
(6)100天python从入门到拿捏《推导式》

您可能感兴趣的与本文相关的镜像

Python3.10

Python3.10

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

硅基工坊

你的打赏是对我最大的鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值