step函数python step函数的傅里叶变换( 二 )


如果要学习 itertools , 那么 Python 官方文档 是你的首选,里面有非常详细的模块相关资料 。但在这篇文章里,侧重点将和官方文档稍有不同 。我会通过一些常见的代码场景 , 来详细解释它是如何改善循环代码的 。
1. 使用 product 扁平化多层嵌套循环
虽然我们都知道“扁平的代码比嵌套的好” 。但有时针对某类需求,似乎一定得写多层嵌套循环才行 。比如下面这段:
?
对于这种需要嵌套遍历多个对象的多层循环代码,我们可以使用 product() 函数来优化它 。product() 可以接收多个可迭代对象,然后根据它们的笛卡尔积不断生成结果 。
?
相比之前的代码,使用 product() 的函数只用了一层 for 循环就完成了任务,代码变得更精炼了 。
2. 使用 islice 实现循环内隔行处理
有一份包含 Reddit 帖子标题的外部数据文件,里面的内容格式是这样的:
?
可能是为了美观,在这份文件里的每两个标题之间,都有一个 "---" 分隔符 。现在,我们需要获取文件里所有的标题列表,所以在遍历文件内容的过程中 , 必须跳过这些无意义的分隔符 。
参考之前对 enumerate() 函数的了解 , 我们可以通过在循环内加一段基于当前循环序号的 if 判断来做到这一点:
?
但对于这类在循环内进行隔行处理的需求来说,如果使用 itertools 里的 islice() 函数修饰被循环对象,可以让循环体代码变得更简单直接 。
islice(seq,start,end,step) 函数和数组切片操作( list[start:stop:step] )有着几乎一模一样的参数 。如果需要在循环内部进行隔行处理的话,只要设置第三个递进步长参数 step 值为 2 即可(默认为 1) 。
?
3. 使用 takewhile 替代 break 语句
有时,我们需要在每次循环开始时,判断循环是否需要提前结束 。比如下面这样:
?
对于这类需要提前中断的循环,我们可以使用 takewhile() 函数来简化它 。takewhile(predicate,iterable)会在迭代 iterable 的过程中不断使用当前对象作为参数调用 predicate 函数并测试返回结果,如果函数返回值为真,则生成当前对象,循环继续 。否则立即中断当前循环 。
使用 takewhile 的代码样例:
?
itertools 里面还有一些其他有意思的工具函数,他们都可以用来和循环搭配使用,比如使用 chain 函数扁平化双层嵌套循环、使用 zip_longest 函数一次同时循环多个对象等等 。
篇幅有限 , 我在这里不再一一介绍 。如果有兴趣,可以自行去官方文档详细了解 。
4. 使用生成器编写自己的修饰函数
除了 itertools 提供的那些函数外,我们还可以非常方便的使用生成器来定义自己的循环修饰函数 。
让我们拿一个简单的函数举例:
?
在上面的函数里 , 循环体内为了过滤掉所有奇数,引入了一条额外的 if 判断语句 。如果要简化循环体内容,我们可以定义一个生成器函数来专门进行偶数过滤:
?
将 numbers 变量使用 even_only 函数装饰后 ,  sum_even_only_v2 函数内部便不用继续关注“偶数过滤”逻辑了,只需要简单完成求和即可 。
Hint:当然,上面的这个函数其实并不实用 。在现实世界里,这种简单需求最适合直接用生成器/列表表达式搞定:sum(numfornuminnumbersifnum%2==0)
建议2:按职责拆解循环体内复杂代码块
我一直觉得循环是一个比较神奇的东西,每当你写下一个新的循环代码块,就好像开辟了一片黑魔法阵,阵内的所有内容都会开始无休止的重复执行 。
但我同时发现,这片黑魔法阵除了能带来好处,它还会引诱你不断往阵内塞入越来越多的代码,包括过滤掉无效元素、预处理数据、打印日志等等 。甚至一些原本不属于同一抽象的内容,也会被塞入到同一片黑魔法阵内 。

推荐阅读