ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
# 16.4. 重识列表映射 你对使用[列表解析](../native_data_types/mapping_lists.html "3.6. 映射 list")映射列表的做法已经熟知。另一种方法可以完成同样的工作:使用内建 `map` 函数。它的工作机理和 [`filter`](filtering_lists.html "16.3. 重识列表过滤") 函数类似。 ## 例 16.10. `map` 介绍 ``` >>> def double(n): ... return n*2 ... >>> li = [1, 2, 3, 5, 9, 10, 256, -3] >>> map(double, li) [2, 4, 6, 10, 18, 20, 512, -6] >>> [double(n) for n in li] [2, 4, 6, 10, 18, 20, 512, -6] >>> newlist = [] >>> for n in li: ... newlist.append(double(n)) ... >>> newlist [2, 4, 6, 10, 18, 20, 512, -6] ``` | | | | --- | --- | | \[1\] | `map` 接受一个函数和一个列表作为参数,\[13\] 并对列表中的每个元素依次调用函数返回一个新的列表。在这个例子中,函数仅仅是将每个元素乘以 2。 | | \[2\] | 使用列表解析的方法你可以做到相同的事情。列表解析是在 Python 2.0 版时被引入的;而 `map` 则古老得多。 | | \[3\] | 你如果坚持以 Visual Basic 程序员自居,通过 `for` 循环的方法完成相同的任务也完全可以。 | ## 例 16.11. `map` 与混合数据类型的列表 ``` >>> li = [5, 'a', (2, 'b')] >>> map(double, li) [10, 'aa', (2, 'b', 2, 'b')] ``` | | | | --- | --- | | \[1\] | 作为一个旁注,我想指出只要提供的那个函数能够正确处理各种数据类型,`map` 对于混合数据类型列表的处理同样出色。在这里,`double` 函数仅仅是将给定参数乘以 2,Python 则会根据参数的数据类型决定正确操作的方法。对整数而言,这意味着乘 2;对字符串而言,意味着把自身和自身连接;对于元组,意味着构建一个包括原始元组全部元素和原始元组组合在一起的新元组。 | 好了,玩够了。让我们来看一些真实代码。 ## 例 16.12. `regression.py` 中的 `map` ``` filenameToModuleName = lambda f: os.path.splitext(f)[0] moduleNames = map(filenameToModuleName, files) ``` | | | | --- | --- | | \[1\] | 正如你在 [第 4.7 节 “使用 lambda 函数”](../power_of_introspection/lambda_functions.html "4.7. 使用 lambda 函数") 中所见,`lambda` 定义一个内联函数。也正如你在 [例 6.17 “分割路径名”](../file_handling/os_module.html#splittingpathnames.example "例 6.17. 分割路径名") 中所见,`os.path.splitext` 接受一个文件名并返回一个元组 `(_name_, _extension_)`。因此 `filenameToModuleName` 是一个接受文件名,剥离出其扩展名,然后只返回文件名称的函数。 | | \[2\] | 调用 `map` 将把 `files` 列出的所有文件名传递给 `filenameToModuleName` 函数,并且返回每个函数调用结果所组成的列表。换句话说,你剔除掉文件名的扩展名,并将剔除后的文件名存于 `moduleNames` 之中。 | 如你在本章剩余部分将看到的,你可以将这种数据中心思想扩展到定义和执行一个容纳来自很多单个测试套件的测试的一个测试套件的最终目标。 ## Footnotes \[13\] 同前,我需要指出 `map` 可以接受一个列表、元组,或者一个像序列一样的对象。参见前面的关于 `filter` 的脚注。