使用map()来调用列表上的函数或更传统的迭代是不是Pythonic?

sco*_*awg 5 python iteration

我有一个带有方法的对象列表,比方说cleanup(),我需要调用所有这些对象.我知道至少有两种方法:

map(lambda x: x.cleanup(), _my_list_of_objects)
Run Code Online (Sandbox Code Playgroud)

要么

for x in _my_list_of_objects:
    x.cleanup()
Run Code Online (Sandbox Code Playgroud)

我的问题:

  1. Pythonic比另一个更多吗?
  2. 还有其他更好的方法吗?我看到前者经常在代码库中使用(在工作中),但它让我觉得地图构造并返回一个然后被丢弃的列表(对吧?).
  3. 是否要考虑对(直接GC的列表)的性能影响?

小智 7

使用map,列表推导,生成器表达式或其他任何对n值应用某些操作并收集结果的方法都不是惯用的.即使您坚持使用不适用的函数式编程概念(即不纯的代码),也存在实际问题:

  • 它浪费了内存和计算累积n个引用(最有可能None),之后会立即丢弃.
  • Python 3 map是懒惰的,所以如果你移植到Python 3 ,这个代码将默默地停止工作(特别是如果你避免2到3 - 有充分的理由).
  • 它很可能更慢,不仅仅是由于第1点,map必须对每个元素执行完整的函数调用,显式循环只需要在字节码级别进行单次跳转.列表理解不需要AFAICT,但在我的简短实验中,它仍然显着慢timeit.

如果你想要一个迭代的每一个元素的东西,那就是究竟该是什么for环路是.干净利落.您将无法获得更多可读性,尽管在某些情况下,某些Python实现上更加模糊的变体可能会更快,但实际上它在可读性方面几乎不值得花费(以及确认它实际上是一个胜利的时间!).


Bak*_*riu 6

  1. for-loop解决方案是更好的,只是因为你不喜欢的结果cleanup.map是python 的功能子集的一部分,使用它来创建副作用是一种使用它的坏方法.

    还要注意mappython2 中的废物空间(因为它创建了一个列表)并且在python3不起作用,你必须使用iterable.在python3中你会有类似的东西:

    from collections import deque
    deque(map(function, iterable), maxlen=0)
    
    Run Code Online (Sandbox Code Playgroud)

    为了在没有空间开销的情况下调用函数,我相信这会丢失很多for-loop可读性.该for-loop解决方案适用于任何 Python版本.

  2. 有很多方法可以做到这一点,但是没有比for-loop 更可读的方法,没有一种方法可以提供显着的性能优势.

  3. 这取决于列表的大小和具体情况.如果代码处于紧密循环中,那么它可能会产生重大影响.然而,python被高度优化以处理小对象,因此如果元素的数量很少,则OS实际上不执行存储器分配.