码农高天称推导式与内建函数较Python手写循环提速近倍

【python】原来我可以少写这么多for loop!学会之后代码都pythonic了起来 — 码农高天

码农高天

手写for循环频繁检索append属性并受制于解释器字节码开销,改用底层C实现的内建函数与列表推导式可大幅削减运行耗时。

AI-assisted summary of 【python】原来我可以少写这么多for loop!学会之后代码都pythonic了起来 — original source. Check the original for full context.

Source published:

Key ideas

  • 列表推导式在字节码层面直接使用专用指令追加元素,省去了每次循环通过命名空间查找 append 方法的开销,性能比手写 for 循环搭配 append 快近一倍。 (0:00)
  • CPython 内置函数(如 max、min)由纯 C 语言编写,循环与临时变量比较无需承受 Python 字节码层面的分支跳转开销,运行效率远高于纯 Python 实现。 (0:00)
  • 在 any 与 all 等具备短路特性的函数中必须传入生成器表达式而非列表推导式,否则会强制全量构建列表,彻底破坏短路求值的性能优势。 (5:00)
  • 内置函数 zip、map 与 filter 均惰性返回生成器,能够优雅替代基于下标索引(range(len(...)))的多序列同步遍历及条件过滤逻辑。 (10:00)

Detailed notes

## Background 该视频由技术博主“码农高天”于 2024 年 4 月 5 日发布在 YouTube 平台上。视频简介指出,本期内容主要面向 Python 初学者,分享几种常用且优雅的替代 for 循环的实现方式,帮助开发者写出更加整洁、地道(Pythonic)的代码。

## TL;DR 视频系统讲解了如何利用 Python 原生特性与内置函数来精简乃至替代传统的 for 循环。码农高天首先对比了列表推导式、生成器表达式与传统循环追加的性能差异,剖析了规避属性查找和纯 C 层面执行的底层加速原理。随后,他深入探讨了 any 与 all 的语义价值及短路求值陷阱,并介绍了 filter、map 与 zip 在数据筛选、变换和多序列对齐场景下的高效用法。整体强调了在编写代码时,应平衡性能开销与可读性,优先选用语义更明确的原生特性。

## Atmosphere & style 整期视频呈现出清晰严谨而又亲切务实的硬核教学风格。博主摒弃了教条式的语法灌输,而是通过现场 benchmark 基准测试、拆解 CPython 底层执行逻辑来辅助论证,展现出深厚的技术底蕴。讲解节奏平稳流畅,在讨论微小的性能损耗与代码可读性时观点客观平衡,给观众带来一种通透易懂且极具实战指导意义的学习体验。

## Bulletin - [00:00](https://www.youtube.com/watch?v=8DJ6M3tvnwY&t=0s) 列表推导式在字节码层面直接使用专用指令追加元素,省去了每次循环通过命名空间查找 append 方法的开销,性能比手写 for 循环搭配 append 快近一倍。 - [00:00](https://www.youtube.com/watch?v=8DJ6M3tvnwY&t=0s) CPython 内置函数(如 max、min)由纯 C 语言编写,循环与临时变量比较无需承受 Python 字节码层面的分支跳转开销,运行效率远高于纯 Python 实现。 - [05:00](https://www.youtube.com/watch?v=8DJ6M3tvnwY&t=300s) 在 any 与 all 等具备短路特性的函数中必须传入生成器表达式而非列表推导式,否则会强制全量构建列表,彻底破坏短路求值的性能优势。 - [10:00](https://www.youtube.com/watch?v=8DJ6M3tvnwY&t=600s) 内置函数 zip、map 与 filter 均惰性返回生成器,能够优雅替代基于下标索引(range(len(...)))的多序列同步遍历及条件过滤逻辑。

## Key takeaways - [00:00](https://www.youtube.com/watch?v=8DJ6M3tvnwY&t=0s) 减少 for 循环并非盲目追求少写代码,而是借助 Python 原生特性与内置函数提升代码运行速度与整洁度。 - [00:00](https://www.youtube.com/watch?v=8DJ6M3tvnwY&t=0s) 初学者习惯先建空列表再通过循环 append 填充,而列表推导式是 Python 中构建 list 更地道、更简洁的解法。 - [00:00](https://www.youtube.com/watch?v=8DJ6M3tvnwY&t=0s) 手写 for 循环中频繁调用 append 存在方法查找(attribute lookup)开销,这是导致其慢于列表推导式的核心瓶颈。 - [00:00](https://www.youtube.com/watch?v=8DJ6M3tvnwY&t=0s) 将列表推导式的方括号替换为圆括号即可生成生成器表达式,因其不预先构建完整列表,其实例化速度呈数量级提升。 - [00:00](https://www.youtube.com/watch?v=8DJ6M3tvnwY&t=0s) Python 优化的首要准则是尽量使用 CPython 提供的 built-in 函数,避免用纯 Python 代码重复造轮子。 - [00:00](https://www.youtube.com/watch?v=8DJ6M3tvnwY&t=0s) 内置 max 函数纯粹在 C 语言层面完成遍历与比较,省去了 Python 解释器在字节码跳转和变量解包上的固有开销。 - [05:00](https://www.youtube.com/watch?v=8DJ6M3tvnwY&t=300s) any 与 all 函数提供了直接表达“是否存在”与“是否全满足”的业务语义,大幅增强了代码的可读性。 - [05:00](https://www.youtube.com/watch?v=8DJ6M3tvnwY&t=300s) 当生成器表达式直接作为函数的唯一实参传入时,Python 允许省略外层圆括号这一语法糖。 - [05:00](https://www.youtube.com/watch?v=8DJ6M3tvnwY&t=300s) 若向 any 或 all 传入列表推导式,会导致整个列表被全量计算,直接导致短路求值(short-circuiting)机制失效。 - [10:00](https://www.youtube.com/watch?v=8DJ6M3tvnwY&t=600s) filter 函数惰性返回一个生成器,当其第一个参数设为 None 时,可快速过滤掉所有假值(Falsy values)。 - [10:00](https://www.youtube.com/watch?v=8DJ6M3tvnwY&t=600s) map 函数支持并发接收多个可迭代对象,在处理多参数转换函数时比嵌套推导式更清晰规整。 - [10:00](https://www.youtube.com/watch?v=8DJ6M3tvnwY&t=600s) 使用 zip 搭配元组解包可以彻底淘汰基于 range(len(...)) 的下标遍历模式,实现多列表的安全对齐。

## Detailed walkthrough ### [00:00](https://www.youtube.com/watch?v=8DJ6M3tvnwY&t=0s) 列表推导式与内建函数的性能优势

在 Python 编程中,`for` 循环是一项基础且频繁使用的结构,但开发者完全可以借助 Python 的原生特性和内置函数来减少 `for` 循环的书写。码农高天强调,这并不是说写 `for` 循环是错的,或者一定要盲目追求少写,而是:“在有一些情况下我们可以用python的一些feature或者built-in functions让你的代码在不使用for loop的情况下实现同样的效果并且更快更正洁”。最典型的场景就是从一个可迭代对象(iterable)构建一个 `list`。初学者或有 C 语言背景的开发者往往习惯先初始化一个空列表,再通过 `for` 循环逐个调用 `append` 往里面塞数据;但在 Python 中更优美的解法是列表推导式(List Comprehension),即形如 `[i for i in range(100)]` 的三段式语法结构。

```mermaid flowchart TD accTitle: 列表推导式结构图 accDescr: 展示 Python 列表推导式由目标元素、循环变量和可迭代对象三部分构成的关系。 subgraph ListComprehension["[ 元素表达式 for 循环变量 in 可迭代对象 ]"] A["目标元素: i"] B["循环变量: i"] C["可迭代对象: range(100)"] end C -->|"遍历"| B B -->|"生成"| A ```

列表推导式不仅代码简洁,在运行速度上也显著超越传统 `for` 循环。使用 `timeit` 模块进行基准测试可以发现,列表推导式比普通 `for` 循环快很多,如果去掉循环内部额外的乘法计算,推导式的速度甚至能快将近一倍。这背后的核心瓶颈在于 `list.append`:在手动执行 `lst.append()` 时,Python 无法预知所调用的具体函数,必须每次先从 `lst` 命名空间中查找并取出 `append` 方法再去执行调用;而列表推导式在字节码层面直接被优化为专用的列表追加指令,避免了属性查找开销。若将推导式的方括号 `[]` 换成圆括号 `()`,则会生成一个生成器表达式(Generator Expression),由于生成器压根不会预先在内存中构建完整列表,其实例化速度相比列表推导式又会有数量级上的提升。

随后,码农高天以两个最简单的内置函数 `max` 和 `min` 为例,直观展示了 Python 内置函数与手写 Python 逻辑之间的性能鸿沟。求最大值本质上不存在高级算法,只能从头到尾逐个比对大小。测试表明,CPython 自带的 `max()` 速度比手写 Python 循环比较快了一倍。这种差距源于 Python 解释器执行字节码(bytecode)带来的固有额外开销(overhead)——将变量写入局部临时变量、条件判断跳转(branching)等操作都需要耗费大量额外时间;而在 C 语言实现的 `max` 函数中,除了必须从 Python 对象解包取值外,循环、比较和临时值存储均在纯 C 层面高速完成。

- **Python 优化的首要准则**:“能用built-in函数完成的代码不要用python写”。 - **列表推导式加速成因**:规避了循环体内反复从列表对象检索 `.append` 属性再执行调用的查找开销。 - **生成器表达式语法**:将列表推导式的方括号替换为圆括号(例如 `(i for i in range(100))`),惰性求值不占用一次性内存。

---

[05:00](https://www.youtube.com/watch?v=8DJ6M3tvnwY&t=300s) 逻辑判断:`any`、`all` 与短路求值的取舍

在业务开发中,遍历一个列表判断是否存在符合条件的元素(存在则立即 `return True`,查无则 `return False`)是极其常见的模式,例如检查列表中是否存在大于 50 的数值。针对这种需求,Python 提供了内置函数 `any` 与 `all`。向 `any` 传入判断逻辑时,写法非常类似于列表推导式:`any(x > 50 for x in lst)`。这里实际传入的是一个生成器,Python 提供了一个语法糖:当生成器表达式本身直接作为函数的唯一实参传入时,可以省略生成器外层的圆括号,使得代码无需书写两层括号,排版更为整洁。

不过性能测试显示,使用 `any` 搭配手写生成器表达式有时会比手写原生 `for` 循环略慢。原因是生成器底层的判断与迭代仍运行在 Python 解释器层面,且生成器的创建与迭代器协议调用本身存在固定的开销;但若待测数据本身已是由布尔值构成的纯列表,内置 `any` 的速度则远胜纯 Python 循环。面对这种细微的性能差别,码农高天明确表态更看重代码的可读性,并指出语义清晰的优势:“当你使用any和all的时候读代码的人可以在更短的时间内意识到你要干什么”。与 `any` 对应,`all` 用于判断可迭代对象中的元素是否全部为真,两者在底层逻辑上高度对称。

在使用这两个函数时,必须警惕误用列表推导式的严重隐患。如果向 `any` 或 `all` 传入列表推导式(即带有方括号的表达式),函数性能会出现断崖式下跌。这是由于 `any` 具有短路特性,一旦发现第一个满足条件的元素就会立刻返回;但列表推导式必须先完整过一遍输入数据把新列表生成出来,再交由 `any` 处理,彻底破坏了短路求值的惰性优势。

- **语法糖机制**:生成器作为函数独立参数时免写额外圆括号(如 `any(x > 50 for x in lst)` 代替 `any((x > 50 for x in lst))`)。 - **`any` 与 `all` 的语义价值**:让代码直接表达“是否存在”与“是否全部满足”的高阶意图。 - **性能陷阱警告**:传参务必坚持使用生成器表达式,严禁使用列表推导式,以确保短路机制正常工作,避免遍历整个列表的冗余开销。

---

[10:00](https://www.youtube.com/watch?v=8DJ6M3tvnwY&t=600s) 数据处理与组合:`filter`、`map` 与 `zip` 的应用

当需要从列表中提取所有满足特定条件的元素时(例如筛选出所有大于等于 60 的数字),传统的方案是遍历列表、使用 `if` 判断并依次 `append`。进阶写法可以直接在列表推导式末尾追加条件判断(如 `[num for num in lst if good_num(num)]`),但内置的 `filter` 函数也是一种非常典雅的选择。`filter` 接收一个判断函数和一个可迭代对象,其返回值是一个生成器而非列表,因此它在功能与性能机制上等价于带有条件的生成器表达式。一个特例是:若将 `filter` 的第一个参数指定为 `None`,它会自动剔除可迭代对象中所有布尔上下文为 False(truthy 检验不通过)的元素。

对于数据变换操作,内置函数 `map` 提供了一种将特定处理函数映射到可迭代对象每个元素的方式,类似于 `(change_num(num) for num in lst)`。在熟悉其用法的前提下,`map` 的表达不仅精简,还在处理多参数输入时具备显著优势:如果转换函数接收两个或更多参数,`map` 可以同时接收多个等长的可迭代对象(如 `map(func, lst1, lst2)`),依次从各个列表中取值并传入函数,这相比于写出极其冗长的推导式要清爽得多。

最后介绍的内置函数是 `zip`,其行为类似于将多条拉链相互咬合。在传统写法中,若想将两个列表中相同索引的元素配对(例如把两个 `0` 到 `99` 的列表组合为 `(0, 0)`, `(1, 1)`... `(99, 99)`),开发者通常需要通过显式索引(index)去定位取值。使用 `zip(list1, list2)` 则可以将其直接打包为一个生成器,每次迭代产生一个元组(tuple)。一个非常实际的应用场景是分散数据的对齐重组:假设我们接收到三个独立列表,分别按序存放了一组人员的名字、年龄与分数;此时无需通过 `range(len(...))` 去循环下标,直接使用 `zip` 便可在迭代时进行元组解包:

```python for name, age, score in zip(names, ages, scores): # 直接获取同一人对应的各项属性数据 ```

这种模式在功能上完全等价于索引迭代,但在代码量、安全性与直观性上都大幅提升。开发者应根据场景与团队直觉,自由在内置高阶函数与推导式/生成器之间进行权衡选取。

- **`filter` 关键特性**:惰性返回生成器;当第一个入参设为 `None` 时,具有自动过滤假值(Falsy values)的特殊功能。 - **`map` 多序列处理能力**:可并发接收多个可迭代对象,消除处理多元参数时推导式过长过乱的问题。 - **`zip` 的解包范式**:结合元组解包(Tuple Unpacking)操作,天然替代基于下标索引的多列表同步遍历。

## Notable quotes > [00:00](https://www.youtube.com/watch?v=8DJ6M3tvnwY&t=0s) 能用built-in函数完成的代码不要用python写 — 码农高天

> [05:00](https://www.youtube.com/watch?v=8DJ6M3tvnwY&t=300s) 当你使用any和all的时候读代码的人可以在更短的时间内意识到你要干什么 — 码农高天

## Mentioned 码农高天, Python, CPython, C语言, timeit

## Video description 这期视频讲一些比较常用的python中替代for loop的方式,非常适合刚入门python的小伙伴。学完之后,代码变得整洁了呢!

[Source](https://www.youtube.com/watch?v=8DJ6M3tvnwY)

中文简报

码农高天称推导式与内建函数较Python手写循环提速近倍 手写for循环频繁检索append属性并受制于解释器字节码开销,改用底层C实现的内建函数与列表推导式可大幅削减运行耗时。 视频系统讲解了如何利用 Python 原生特性与内置函数来精简乃至替代传统的 for 循环。码农高天首先对比了列表推导式、生成器表达式与传统循环追加的性能差异,剖析了规避属性查找和纯 C 层面执行的底层加速原理。随后,他深入探讨了 any 与 all 的语义价值及短路求值陷阱,并介绍了 filter、map 与 zip 在数据筛选、变换和多序列对齐场景下的高效用法。整体强调了在编写代码时,应平衡性能开销与可读性,优先选用语义更明确的原生特性。 列表推导式在字节码层面直接使用专用指令追加元素,省去了每次循环通过命名空间查找 append 方法的开销,性能比手写 for 循环搭配 append 快近一倍。 (0:00) CPython 内置函数(如 max、min)由纯 C 语言编写,循环与临时变量比较无需承受 Python 字节码层面的分支跳转开销,运行效率远高于纯 Python 实现。 (0:00) 在 any 与 all 等具备短路特性的函数中必须传入生成器表达式而非列表推导式,否则会强制全量构建列表,彻底破坏短路求值的性能优势。 (5:00) 内置函数 zip、map 与 filter 均惰性返回生成器,能够优雅替代基于下标索引(range(len(...)))的多序列同步遍历及条件过滤逻辑。 (10:00)

Reading summary

码农高天指出,开发者可以通过合理使用 Python 的内置函数与推导式特性来减少原生 `for` 循环的书写,从而在不失清晰度的情况下显著提高代码运行效率与可读性。 列表推导式与内置函数的底层性能优势 (0:00) 在从可迭代对象构建新列表时,相较于先声明空列表再通过 `for` 循环逐个调用 `append` 的传统写法,形如 `[i for i in range(100)]` 的列表推导式具备显著的执行速度优势。使用 `timeit` 进行基准测试显示,在剔除循环内额外运算后,推导式速度可比普通循环快将近一倍。这主要是因为列表推导式在字节码层面被优化为专用追加指令,规避了每次循环中从列表命名空间检索 `.append` 属性并调用的固有开销。将方括号替换为圆括号则可构建生成器表达式,因其不预先在内存中分配完整列表,其实例化速度有数量级提升。 内置函数在底层由 C 语言实现,其执行效率同样远超纯 Python 逻辑。以 `max()` 与 `min()` 为例,求极值本质上只能遍历比对,但 CPython 自带的 `max()` 速度比手写 Python 循环比较快了一倍。手写循环需要耗费时间处理局部临时变量写入和条件判断跳转等解释器字节码开销,而 C 实现的函数只需解包 Python 对象,比较与存储均在 C 层面完成。码农高天据此提出 Python 优化的首要准则:“能用 built-in 函数完成的代码不要用 python 写”。 逻辑断言函数中的短路机制与语法权衡 (5:00) 在判断列表中是否存在满足特定条件的元素时,内置函数 `any` 与 `all` 提供了清晰的语义化方案,如使用 `any(x > 50 for x in lst)`。当生成器表达式作为函数的唯一实参传入时,Python 允许省略外层圆括号这一语法糖,使代码更为整洁。尽管基准测试表明手写生成器配合 `any` 有时会因为生成器创建与迭代器协议调用的额外开销而略慢于原生循环(除非输入本身已是布尔值列表),但码农高天更强调可读性价值,认为 `any` 和 `all` 能让阅读者在更短时间内明确代码意图。 使用断言函数时需注意避免误传入列表推导式(即包含方括号的形式)。`any` 具备短路求值特性,只要遇到首个满足条件的元素便会立即返回;若误用列表推导式,Python 将被迫在内存中一次性遍历并构建整个新列表,彻底破坏了短路惰性求值的优势,导致性能断崖式下跌。 利用 filter、map 与 zip 简化数据流处理 (10:00) 对于数据的筛选与映射,内置高阶函数提供了贴合原生特性的替换方案。`filter` 接收判断函数与可迭代对象并惰性返回生成器,功能与条件推导式相当;当第一个参数设为 `None` 时,它具备自动剔除所有假值(Falsy values)的特殊机制。对于数据变换,`map` 在单序列映射时类似于生成器推导式,而在处理接收多元参数的转换函数时表现更佳,可同时接收多个等长的可迭代对象(如 `map(func, lst1, lst2)`),避免写出过于冗长杂乱的推导式。 针对多序列按位置配对的需求,内置函数 `zip` 可以直接将多个列表打包成生成元组的迭代器,摆脱了以往依赖 `range(len(...))` 的显式下标索引遍历模式。例如在同步读取分散存放的姓名、年龄和分数列表时,直接使用 `for name, age, score in zip(names, ages, scores)` 配合元组解包,既减少了代码量,又消除了越界风险,提升了数据对齐的直观性。 减少 `for` 循环并不意味着循环结构本身存在缺陷,而是在具体场景中,合理选用列表推导式、生成器以及 `max`、`any`、`filter`、`map`、`zip` 等内置工具,能够依托底层 C 实现和惰性求值特性,兼顾执行性能与直观的代码表达。

Source quotes

[0:00] 码农高天: 能用built-in函数完成的代码不要用python写 [5:00] 码农高天: 当你使用any和all的时候读代码的人可以在更短的时间内意识到你要干什么

Original transcript

[0:00] 这期视频我们要讲的内容跟Fool有关大家知道在python里面for loop是一个非常非常重要而且常用的结构但是我们今天要给大家讲的是如何少写for loop当然我不是说写for loop就是错的或者你能少写就少写而是说在有一些情况下我们可以用python的一些feature或者built-in functions让你的代码在不使用for loop的情况下实现同样的效果并且更快更正洁好 我们看左边第一个例子这个例子很多朋友可能已经很熟悉了我们拿它作为开头这个例子包含了一大类情况就是我们要从一个iterable建立一个list的过程我们看如果你是初学python或者你是从c转过来的 你很有可能就会这么写建立一个空的list然后做一个负尔循环逐渐的往list里面append东西这是一个正确的写法但是在python里这不是一个足够好的写法更好的写法是第10行这行代码这种写法的术语叫做List Comprehension这个list comprehension分为三个部分后面这一块是一个for-in结构很明显最后一个部分是一个interval对应上面的range100中间这个爱和full loop里面的爱意思是一样的 都是循环变量而前面这个爱是我想组成列表的元素如果这两个i看起来不清楚的话我们把代码改一下大家可以看这两端代码是等价的如果你比较熟悉List Comprehension这个写法的话你就会发现它是比上面的写法要简洁不少的而实际上它不光更简洁而且更快我们用timeit来测试一下这两个函数的运行速度可以看到List Comprehension比我们传统的Full Loop要快了非常多那如果我们把这个惩罚给拿掉的话Least comprehension的速度快了会将近一倍这里面最大的影响因素实际上是append函数当你在做list.append的时候Python没有办法直接判断你使用的就是list的append函数所以他需要从LST里面先找到append函数再拿出来再调用它而当你使用List Comprehension的时候Python就可以直接去调用那个list的append函数了有的时候我们会见到这样的表达式就是刚才的 least comprehension 把中括号变成了原括号这样我们实际上是生成了一个generator生成器不知道generator是什么的去看我之前的视频由于我压根就没有建立这个list 而是建立了一个generator这个操作比刚才的Least Comprehension还要快非常多大家可以看一下这就差数量极了大家要记住这个generator的形式 我们等会用个道接下来我们要介绍的是两个非常简单的built-in函数Max和Min这两个函数非常容易理解分别是求iterable里面的最大值和最小值为什么要聊这么简单的函数是想让大家知道一下built-in函数的速度和你自己写的python速度差多少我们知道球最大值是一个非常简单的事情它也没有任何fancy的算法他只能一个一个拿出来比大小也就是说算法层面上我们这里已经写的是最简单的算法了而我们运行一下就会发现Python自在的built-in的max比我们自己实现的max要快了一倍这个速度的差距主要是因为我们在运行python代码的时候这些字节码带来的overhead比如说当我们把变量保存进一个local的临时变量的时候再比如说我们判断然后branch的时候当我们运行这些python的bytecode的时候我们实际上花费了很多不必要的时间而在cpython用c实现的max里尽管我也需要从这个python object里面一个一个往外拿东西但是在保存、循环、判断的时候我都可以在C层面进行因此就抢出了很多的速度那这个也是python优化的第一个技巧就是能用built-in函数完成的代码不要用python写好那接下来我们介绍两个稍微 [5:00] 不那么常见的函数一个叫做any 一个叫做all我们看这段拍仓代码这也是我们很常见的一个pattern就是我们找遍一个list然后如果发现一个什么样的东西直接return true否则Return False比如说我想找找这个list里面有没有一个大于50的数对于这种在一个Iterable里面寻找有没有一个这样的东西的任务我们可以用any来完成大家注意,这个any里面,我直接写了一个非常像list comprehension的东西它实际上是我们刚刚提到的generator你可能说 哎不对呀 这个括号对不上 对吧这个generator应该是长成下面这个样子的这个里面generator本身有个括号然后外面函数调用再有一个括号它应该是两层括号这里就是拍散了一个小小的语法堂当你把这个generator本身当做一个argument传件函数里的时候generator的那个括号就会不用写了这样让你的代码会看起来更整洁一些好 我们看这两种写法的对比明显是用built-in函数的写法在语义上更清晰用人话来说就是可读性更好但是这里注意一下啊如果你运行一下benchmark 你会发现使用any会比直接写python还要慢一些这里的原因呢是我们这个generator本身啊还是运行在python层面的所以呢这个不用any的代码要做的东西我们基本上都做了而generate的建立和调用本身它是有代价的所以使用ANY反而更慢了事实上如果我们没有这个Generator而是直接在一个List里面找True的话any是比python的写法要快的我个人还是会更喜欢用built-in函数这个写法因为它的可图性是更好的和 Annie相对的当我们判断一个iterble里面是不是全都是true的时候我们可以使用all观察一下可以发现any和all对应的python代码实际上是非常相似的这里就体现了我前面提到的语意的重要性当你使用any和all的时候读代码的人可以在更短的时间内意识到你要干什么这里我们注意一下 如果我们在使用any的时候传进去的是一个列表表达式那它的速度又会明显的更慢一些为什么呢?因为对于Annie来说,她只要看到一个满足提议的就可以返回了也就是如果你使用generator的话他不需要把list里面每一个东西都拿到而如果你用list comprehension,他就需要先把整个list过一遍然后再把这个list传给Annie那这样就显然慢了所以当我们在使用any或者all的时候一定要记得使用Generator而不用List comprehension好 那我们接下来介绍一些稍微有一点难度的用法假如说我有一个list 同时我还有一个判断函数来判断一个值我想不想要然后我想找到这个list里面所有满足我这个判断函数的值比如说在现在这个程序里面我想找到这个list里面所有大于等于60的数那传统的写法非常直观 过一遍list如果这个判断成立的话我加进去最后把返回的利润给返回那实际上你完全可以用list comprehension来实现这个事情你只需要在我们之前讲的list comprehension后面加一个condition加一个if也就是只有goodnum的时候才把NUN放到这个list里但是呢 在这里我们也介绍一个使用built-in function的方法我们可以使用一个Future函数Future函数的第一个argument是一个判断函数第二个argument是一个iterable他会从这个iterable里面把所有的值拿出来然后拿这个判断函数判断一下和我们刚才说的是同一个功能这里要注意一下filter这个函数返回的并不是一个list而是一个generator也就是说它并不等价于我们刚才的 least comprehension它基本等价于把刚才的那个list comprehension里面的方括号变成原括号也就是Generator唯一一个小小的不同是如果他的第一个argument传出 [10:00] 觉得是难的话他就会把这个list里面所有evaluate成false的东西给剔除那你是更喜欢写list comprehension或者generator还是更喜欢用built-in function就要看你自己觉得哪一种语义对你来说更可毒了与之相似的还有卖盘数刚才的filter是用第一个函数来判断这个值要不要而卖盘数相当于是做了一个映射比如我们这里把所有的number都变成了number乘以2当然他就等价于这个generator change num for num in list我们看在你熟悉这种用法的情况下它使用的代码的数量是更少的在雨意上也稍稍清晰一点当然 对于map来说 它还有另外一个优势就是他可以接受多个 argument我们看假如这个change函数需要两个inputMap可以从两个不同的iterable里面取出这个值然后放到这个函数里并且拿到返回值当argument多的时候你就会发现上面这个generator的表达式会变得有一些冗长了好 那我们最后介绍一个函数叫做Zip我们有的时候会想把两个itrable像拉拉链那样把它们给揉在一起我们看传统的实现方式我们通过index来把list和list2里面index相同的变量放到一个tuple里面然后把这一串给返回也就是说 原来两个list分别是0到99 0到99而我新的list是00 11 22 33 这样一直到99 99而使用这盘数可以等价的实现这样的功能当然,它返回的也是一个generator,而不是一个list我们可以看到在这个例子下ZIP明显就比上面的传统的实现方式要简洁的多关于ZIP 我们这里给一个例子让大家感受一下我们看假如说我们 somehow拿到了一个数据是这样的他有三个人但是它的名字 它的年龄 它们的分数都是分别以一个list形式传进来的同一个index是同一个人的数据我们怎么拿到属于同一个人的数据呢我们可以通过一个传统的负货循环去对这个index做循环然后把这些数值都拿到我们这里也可以使用V盘数由于Z盘数返回的是一个generator而这个generator每次产生的是一个cupine我们可以直接把它unpack存到name,edge, score里这两个函数在功能上是增加的好 那这期视频就到这里 希望对大家有所帮助 喜欢的话记得点下关注 别忘了意见三连哦!优优独播剧场——YoYo Television Series Exclusive