python可迭代对象、迭代器和生成器

本文介绍了Python中的迭代器和生成器的概念及其区别。迭代器以延迟计算的方式节省内存,而生成器是迭代器的一种,实现了懒加载的模式。通过实例展示了列表与迭代器的不同行为,以及如何使用生成器实现斐波那契数列。此外,还解释了生成器函数中的yield关键字以及next()和send()方法的用法。

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

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

迭代器与列表的区别在于,构建迭代器的时候,不像列表把所有元素一次性加载到内存,而是以一种延迟计算(lazy
evaluation)方式返回元素,这正是它的优点。比如列表中含有一千万个整数,需要占超过100M的内存,而迭代器只需要
几十个字节的空间。因为它并没有把所有元素装载到内存中,而是等到调用next()方法的时候才返回该元素(按需调用
call by need 的方式,本质上 for 循环就是不断地调用迭代器的next()方法)。

1.1 案例:列表与迭代器

  • 列表不论遍历多少次,表头位置始终是第一个元素
  • 迭代器遍历结束后,不再指向原来的表头位置,而是为最后元素的下一个位置
# 列表与迭代器的区别
a = [1, 3, 5, 7]
a_iter = iter(a)

print('第一次遍历\n列表:')
for i in a:
    print(i, ' ', end='')
print('\n迭代器:')
for i in a_iter:
    print(i, ' ', end='')

print('\n第二次遍历\n列表:')
for i in a:
    print(i, ' ', end='')
print('\n迭代器:')
for i in a_iter:
    print(i, ' ', end='')
  • 运行结果:
第一次遍历
列表:
1  3  5  7  
迭代器:
1  3  5  7  
第二次遍历
列表:
1  3  5  7  
迭代器:

进程已结束,退出代码0

2. 生成器

  • 生成器一定是迭代器(反之不成立),因此任何生成器也是一种懒加载的模式生成值。下面来用生成器来实现斐波那契数列的例子:
def fib(max):
    prev, curr = 0, 1
    while max > 0:
        max -= 1
        yield curr
        prev, curr = curr, prev + curr

if __name__ == '__main__':
    fib = fib(6)
    # 调用next()的过程
    for n in fib:
        print(n)
    # raise StopIteration
    print(next(fib))
  • 上面是生成器函数,再来看下生成器的表达式,生成器表达式是列表推导式的生成器版本,看起来像列表推导式,但是它返回的是一个生成器对象而不是列表对象。
>>> x = (x*x for x in range(10))
>>> type(x)
<class 'generator'>
>>> y = [x*x for x in range(10)]
>>> type(y)
<class 'list'>
  • 我们再看看一个例子:
# 函数有了yield之后,函数名+()就变成了生成器
# return在生成器中代表生成器的中止,直接报错
# next的作用是唤醒并继续执行
# send的作用是唤醒并继续执行,发送一个信息到生成器内部

import time

def func(n):
    for i in range(0, n):
        # yield相当于return,下一次循环从yield的下一行开始
        arg = yield i
        print('func', arg)

if __name__ == '__main__':
    f = func(6)
    while True:
        print('main-next:', next(f))
        print('main-send:', f.send(100))
        time.sleep(1)
  • 运行结果为:
main-next: 0
func 100
main-send: 1
func None
main-next: 2
func 100
main-send: 3
func None
main-next: 4
func 100
main-send: 5
func None
Traceback (most recent call last):
  File "demo.py", line 13, in <module>
    print('main-next:', next(f))
StopIteration
  • yield就是return返回一个值,并且记住这个返回的位置,下次迭代就从这个位置后(下一行)开始。next方法和send方法都可以返回下一个元素,区别在于send可以传递参数给yield表达式,这时传递的参数会作为yield表达式的值,而yield的参数是返回给调用者的值。

参考链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值