我有一个带有方法的对象列表,比如cleanup()
,我需要在所有对象上调用它们。我知道至少有两种方式:
map(lambda x: x.cleanup(), _my_list_of_objects)
或
for x in _my_list_of_objects:
x.cleanup()
我的问题:
答案 0 :(得分:7)
It is not idiomatic使用map
,列表推导,生成器表达式 - 或对n值应用某些操作并收集结果的其他任何内容 - 用于副作用。即使您坚持使用不适用的函数式编程概念(即不纯的代码),也存在实际问题:
None
),之后会立即丢弃。map
是懒惰的,所以如果你移植到Python 3,这个代码静默就会停止工作(特别是如果你避免2到3 - 有充分的理由)。map
必须对每个元素执行一个完整的函数调用,显式循环只需要在字节码级别进行一次跳转。列表理解不需要AFAICT,但在timeit
的简短实验中它仍然明显变慢。如果你想为可迭代的每个元素做某事,那就完全 for
循环的用途。干净利落。你将不再具有可读性,虽然在某些情况下,在某些Python实现中,更加模糊的变体可能会更快,但它几乎不值得花费可读性(以及验证它实际上是赢的时间!)。
答案 1 :(得分:6)
for
- 循环解决方案更好,因为您不关心cleanup
的结果。 map
是python的功能子集的一部分,使用它创建副作用是一种使用它的坏方法。
另请注意,map
会浪费python2中的空间(因为它会创建一个列表),而在python3中不起作用,您必须使用iterable。在python3中你会有类似的东西:
from collections import deque
deque(map(function, iterable), maxlen=0)
为了在没有空间开销的情况下调用函数,我相信这会消除for
- 循环可读性的大部分内容。 for
- 循环解决方案适用于任何 python版本。
有很多方法可以做到这一点,但没有比for
- 循环更可读的方法,而且没有任何方法可以提供显着的性能优势。
这取决于列表的大小和具体情况。如果代码处于紧密循环中,那么它可能会产生重大影响。然而,python经过高度优化以处理小对象,因此如果元素数量很少,则操作系统实际上不会执行内存分配。
答案 2 :(得分:0)
所以,我一直使用map()作为'在列表中的一堆对象上调用此函数'的简写。毕竟,列表推导(通常)比在循环中做同样的事情更快,所以为什么不映射?
无论如何,结果如下:
r = [[] for _ in range(10000)]
%timeit map(lambda y: r[y].append(1), x)
100 loops, best of 3: 2.56 ms per loop
r = [[] for _ in range(10000)]
%%timeit
for y in x:
r[y].append(1)
1000 loops, best of 3: 1.67 ms per loop
对于这种情况,甚至没有关闭 - for循环方法的速度大约是其两倍。