第 20 章 理解和世代
本作品已使用人工智能进行翻译。欢迎您提供反馈和意见:translation-feedback@oreilly.com
本章继续高级函数主题,重述第 4 章预览和第 14 章介绍的理解和迭代概念。由于理解与前一章中的函数工具(如map 和filter )以及for 循环有着密切的关系,我们将在这里重新讨论它们。我们还将对迭代式进行第二次考察,以研究生成器函数及其生成器表达式的亲戚--用户定义的按需生成结果的方法。
Python 中的迭代还包括用户定义的类,但我们将把这个故事的最后一部分推迟到第六部分,即研究操作符重载时。由于这是我们最后一次使用内置迭代工具,我们将总结迄今为止我们遇到的各种工具。下一章将继续这条主线,将这些工具的相对性能作为一个更大的案例进行计时研究。在此之前,让我们继续讲述理解和迭代的故事,并将其扩展到值生成器。
列表理解和功能工具
正如本书的开头提到的,Python 支持过程式、面向对象和函数式编程范式。事实上,Python 拥有大量大多数人认为是函数性质的工具,我们在上一章中列举了这些工具--闭包、生成器、Lambda、理解、映射、装饰器、函数对象等等。这些工具允许我们以强大的方式应用和组合函数,并经常提供状态保持和编码解决方案,以替代类和 OOP。
例如,上一章探讨了map 和filter等工具--这些工具是 Python 早期函数式编程工具集的主要成员,其灵感来自 Lisp 语言--它们可以映射迭代器上的操作并收集结果。由于这在 Python 代码中是如此常见的任务,Python 最终萌生了一种新的表达式--list comprehension--它比我们刚才学习的工具更加灵活。
根据 Python 的历史,列表理解最初是受到函数式编程语言 Haskell 中类似工具的启发,时间大约在 Python 2.0 时代。简而言之,列表理解将任意表达式应用到可迭代项中,而不是应用函数。因此,它们可以成为更通用的工具。在后来的版本中,理解扩展到了其他角色--集合、字典,甚至是我们将在本章探讨的值生成器表达式。它不再仅仅适用于列表。
我们在第 4 章的预览中第一次见到了 list 解析,并在第 14 章结合循环语句进一步学习了它们。不过,由于它们也与函数式编程工具(如map 和filter 调用)有关,因此我们在这里再次讨论这个话题,做最后一次回顾。从技术上讲,这个特性与函数无关--正如我们将看到的,列表理解可以是比map 和filter更通用的工具--但有时最好通过类比基于函数的替代方法来理解它。
列表理解与地图
让我们通过一个示例来演示基础知识。正如我们在第 7 章中看到的,Python 内置的ord 函数返回单个字符的整数码位(内置的chr 与相反,它返回整数码位的字符)。如果您的字符属于 ASCII 字符集的 7 位码位范围,这些正好是ASCII 码:
>>> ord('s')
115现在,假设我们希望收集整个字符串中所有字符的 ASCII 码。也许最直接的方法就是使用一个简单的for 循环,并将结果追加到一个列表中:
>>>res = []>>>for x in 'spam':res.append(ord(x))# Manual results collection>>>res[115, 112, 97, 109]
既然我们已经知道了map ,那么我们只需调用一个函数就能获得类似的结果,而无需在代码中管理列表构造:
>>>res = list(map(ord, 'spam'))# Apply function ...
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