使用 map() 与 for 有什么价值?
-
22-08-2019 - |
题
map() 是否像“for”一样迭代列表?使用 map 与 for 是否有价值?
如果是这样,现在我的代码如下所示:
for item in items:
item.my_func()
如果有意义的话,我想把它做成map()。那可能吗?一个例子是什么样的?
解决方案
你可以使用 map
而不是 for
您已经展示了循环,但由于您似乎没有使用 item.my_func()
, , 这是 不建议. map
如果您想对列表的所有元素应用没有副作用的函数,则应使用。在所有其他情况下,请使用显式 for 循环。
另外,从 Python 3.0 开始 map
返回一个生成器,所以在这种情况下 map
不会表现相同(除非您明确评估生成器返回的所有元素,例如通过致电 list
在上面)。
编辑: 吉比布 在评论中要求澄清原因 map
的第一个参数不应该是有副作用的函数。我会尝试回答这个问题:
map
旨在传递一个函数 f
在数学意义上. 。在这种情况下,按什么顺序并不重要 f
应用于第二个参数的元素(只要它们是 回 当然,按照原来的顺序)。更重要的是,在这种情况下 map(g, map(f, l))
在语义上等价于 map(lambda x: g(f(x)), l)
, 无论顺序如何 f
和 g
应用于各自的输入.
例如,是否并不重要 map
立即返回迭代器或完整列表。然而,如果 f
和/或 g
引起副作用,那么只有当语义 map(g, map(f, l))
使得在任何阶段 g
应用于第一个 n 返回的元素 map(f, l)
前 map(f, l)
适用 f
到 (n+1)的第一个元素 l
. 。(意思是 map
必须执行尽可能最懒的迭代——Python 3 中是这样做的,但 Python 2 中不是!)
更进一步:即使我们假设 Python 3 实现 map
, ,如果输出 map(f, l)
例如通过传递 itertools.tee
在供应给外部之前 map
称呼。
上述讨论可能看起来是理论上的,但随着程序变得越来越复杂,它们变得更难以推理,因此更难调试。确保某些事情不变可以在一定程度上缓解该问题,并且实际上可以防止一整类错误。
最后, map
让许多人想起了各种(纯)函数式语言中真正的函数式对应物。向它传递一个带有副作用的“函数”会让那些人感到困惑。因此,将其视为替代方案(即使用显式循环)并不比调用更难实现 map
, ,强烈建议限制使用 map
适用于要应用的功能不会引起副作用的情况。
其他提示
可以写此使用图像这样:
map(cls.my_func, items)
与类你迭代的物品的替换CLS。
正如Stephan202提到的,这是的不推荐强>在这种情况下。
作为一个规则,如果你想在应用列表中的一些功能,每一个项目建立一个新的列表,使用地图。这暗示这意味着函数没有副作用,因此你可以(可能)并行运行地图。
如果你不希望创建一个新的列表,或者如果函数有副作用,使用for循环。这是在你的例子的情况。
有一个轻微的语义差异,这是在Python语言规范可能关闭。在地图的是明确并行,而为的只有在特殊情况下。代码可以破出从的的,但仅与异常从逸出地图
在我看来的地图的不应该也保证功能应用,而为的必须订购。据我所知没有Python实现是目前能够做到这一点的自动并行化。
如果您需要将您可以将您map
一些很酷的螺纹或多核或分布式计算框架。 迪斯科是分布式的,对故障的erlang抗性和 - 基于蟒框架的一个例子。我将其配置于8芯的2盒现在我的程序运行感谢16倍的速度,向迪斯科簇,但是我不得不从列表解析重写我方案和循环映射/降低。
这是相同的协议,编写使用for循环和列表理解和地图/减少程序,但是当你需要它在集群上运行,你可以,如果你使用的map / reduce做到这一点几乎是免费的。如果你没有,那么,你将不得不改写。
请注意:如据我所知,蟒2.x的返回一个列表,而不是从图的迭代器。我听说这可以通过使用iter.imap()
旁路(从未使用过它虽然)。
使用明确的for循环,当你不需要的结果列表后面(例如,有副作用的函数)。
使用列表理解,当你确实需要一个结果列表返回(返回直接基于输入值,例如函数)。
当你试图说服Lisp的用户Python是值得使用使用地图()。 ;)
map
的主要优点是,当你想在一个列表中的每个元素上的一些计算的结果。例如,这个片段在列表中的每一个值加倍:
map(lambda x: x * 2, [1,2,3,4]) #=> [2, 4, 6, 8]
要注意的是map
返回的结果一个新的名单是很重要的。它不会修改到位原始列表。
做for
同样的事情,你需要创建一个空的列表,并添加一个额外的行到for
身体补充每个计算新名单的结果。所述map
版本更加简洁和功能性。
地图有时可以比手动编码for循环更快的内置函数。尝试时序图(STR,范围(1000000))相对于一个类似的for循环。
map(lambda item: item.my_func(), items)