第 5 章 迭代器和生成器
本作品已使用人工智能进行翻译。欢迎您提供反馈和意见:translation-feedback@oreilly.com
当许多有其他语言经验的人开始学习 Python 时,他们会对for 循环符号的不同感到吃惊。 也就是说,不写
#Other languagesfor(i=0;i<N;i++){do_work(i);}
它们被引入一个名为range 的新函数:
# Pythonforiinrange(N):do_work(i)
在 Python 示例代码中,我们似乎在调用一个函数range ,它创建了for 循环继续所需的所有数据。直观地说,这可能是一个相当耗时的过程--如果我们要循环遍历 1 到 100,000,000 的数字,那么我们就需要花费大量时间来创建数组!然而,这正是生成器发挥作用的地方:从本质上讲,生成器允许我们懒散地评估这些函数,因此我们可以获得这些特殊用途函数的代码可读性,而不会对性能造成影响。
为了理解这一概念,让我们实现一个函数,通过填充列表和使用生成器来计算几个斐波那契数字:
deffibonacci_list(num_items):numbers=[]a,b=0,1whilelen(numbers)<num_items:numbers.append(a)a,b=b,a+breturnnumbersdeffibonacci_gen(num_items):a,b=0,1whilenum_items:yieldaa,b=b,a+bnum_items-=1
首先要注意的是, fibonacci_list 实现必须创建并存储所有相关斐波那契数字的列表。 因此,如果我们想要 10,000 个序列的数字,函数将对numbers 列表进行 10,000 次追加(正如我们在第 3 章中讨论过的,追加会产生开销),然后返回。
另一方面,生成器能够 "返回 "许多值。 每当代码运行到yield 时,函数就会输出其值,而当请求另一个值时,函数就会恢复运行(保持先前状态)并输出新值。 当函数运行到终点时, StopIteration 异常,表明给定的生成器没有更多的值。 因此,尽管两个函数最终必须进行的计算次数相同,但fibonacci_list 版本的前一个循环使用的内存要多 10,000 倍(或num_items 倍)。
有了这些代码,我们就可以分解使用我们实现的fibonacci_list 和 fibonacci_gen 的 for 循环。在 Python 中,for 循环要求我们要循环的对象支持迭代。 ...
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access