这段代码是如何产生初始的 a 值? 'Sam' 出现次数的初始值不能是 'Mary read a story to Sam and Isla.' 。初始累加器用 reduce() 的第三个参数指定。这样就允许使用与集合元素不同类型的值。
为什么 map 和 reduce 更好?
- 这样的做法通常会是一行简洁的代码。
- 迭代的重要部分 —— 集合、操作和返回值 —— 以
map 和 reduce 方式总是在相同的位置。
- 循环中的代码可能会影响在它之前定义的变量或在它之后运行的代码。按照约定,
map 和 reduce 都是函数式的。
map 和 reduce 是基本原子操作。
- 阅读
for 循环时,必须一行一行地才能理解整体逻辑。往往没有什么规则能保证以一个固定结构来明确代码的表义。
- 相比之下,
map 和 reduce 则是一目了然表现出了可以组合出复杂算法的构建块( building block )及其相关的元素,代码阅读者可以迅速理解并抓住整体脉络。『哦~这段代码正在转换每个集合元素;丢弃了一些转换结果;然后将剩下的元素合并成单个输出结果。』
map 和 reduce 有很多朋友,提供有用的、对基本行为微整的版本。比如: filter 、 all 、 any 和 find 。
练习2:尝试使用 map 、 reduce 和 filter 重写下面的代码。 filter 需要一个函数和一个集合,返回结果是函数返回 True 的所有集合元素。
- people = [{'name': 'Mary', 'height': 160},
- {'name': 'Isla', 'height': 80},
- {'name': 'Sam'}]
-
- height_total = 0
- height_count = 0
- for person in people:
- if 'height' in person:
- height_total += person['height']
- height_count += 1
-
- if height_count > 0:
- average_height = height_total / height_count
-
- print average_height
- # => 120
如果上面这段代码看起来有些烧脑,我们试试不以在数据上操作为中心的思考方式。而是想一想数据所经历的状态:从人字典的列表转换成平均身高。不要将多个转换混在一起。每个转换放在一个单独的行上,并将结果分配一个有描述性命名的变量。代码工作之后,再合并缩减代码。
我的实现方案:
- people = [{'name': 'Mary', 'height': 160},
- {'name': 'Isla', 'height': 80},
- {'name': 'Sam'}]
-
- heights = map(lambda x: x['height'],
- filter(lambda x: 'height' in x, people))
-
- if len(heights) > 0:
- from operator import add
- average_height = reduce(add, heights) / len(heights)
声明方式编写代码,而非命令式
下面的程序演示三辆赛车的比赛。每过一段时间,赛车可能向前跑了,也可能抛锚而原地不动。在每个时间段,程序打印出目前为止的赛车路径。五个时间段后比赛结束。
这是个示例输出:
- -
- --
- --
-
- --
- --
- ---
-
- ---
- --
- ---
-
- ----
- ---
- ----
-
- ----
- ----
- -----
这是程序实现:
- from random import random
-
- time = 5
- car_positions = [1, 1, 1]
-
- while time:
- # decrease time
- time -= 1
-
- print ''
- for i in range(len(car_positions)):
- # move car
- if random() > 0.3:
- car_positions[i] += 1
-
- # draw car
- print '-' * car_positions[i]
这份代码是命令式的。函数式版本则是声明性的,描述要做什么,而不是如何做。
使用函数 (编辑:好传媒网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|