当我们不关心输出时,Python 内置习惯用法将函数应用于可迭代对象的每个元素

标签 python python-3.x

假设您有一个返回 None 的函数(有趣的部分是副作用,例如日志记录、更新、保存、通过管道推送...),或者您不返回的值确实需要。现在你想把这个函数应用到一个可迭代的对象上。你是怎么做到的?

在某些情况下使用 map 既不优雅也不高效,因为我们需要使用它来执行它。

_ = list(map(print, ['hello', 'world']))

如果可迭代对象很小,那很好,但你不想对大的可迭代对象这样做。所以你可以这样做:

def apply(func, *iterables):
    for items in zip(*iterables):
        func(*items)

这会给我们想要的效果:

>>> apply(print, ['hello', 'world'])
hello
world
>>> apply(lambda x, y: print(x + y), [1, 2], [3, 4])
4
6
>>> from collections import Counter
>>> c = Counter()
>>> apply(c.update, ['green', 'eggs'])
>>> c
Counter({'g': 3, 'r': 1, 'e': 3, 'n': 1, 's': 1})

难道没有内置技巧吗?因为 map 对于较小的可迭代对象来说似乎更快,但是内存成本很高,我想这在某些时候开始使它成为最慢的选项:

>>> from timeit import timeit
>>> from collections import Counter
>>>
>>> iterable = ['green', 'eggs', 'and', 'ham'] * 10000
>>> timeit("c = Counter(); apply(c.update, iterable);", number=100, globals=globals())
2.7703
>>> timeit("c = Counter(); _ = list(map(c.update, iterable));", number=100, globals=globals())
2.6981
>>>
>>> iterable = ['green', 'eggs', 'and', 'ham'] * 100000
>>> timeit("c = Counter(); apply(c.update, iterable);", number=100, globals=globals())
27.4498
>>> timeit("c = Counter(); _ = list(map(c.update, iterable));", number=100, globals=globals())
30.4676

最佳答案

Python 内置函数中没有任何内容是专门为此目的而制作的。但是,有一些设计注意事项。

存在内存/速度权衡。如果您使用列表理解,则会有一个结果列表,该列表存储在内存中。

# the result is not assigned anywhere, but the list is still created
[my_func(*args) for args in somme_iterable]

是的,None 是一个单例,但每个列表项的开销很小;对于非常大的可迭代对象,它可能很大。如果您使用 for 循环,您可以简单地省略结果。

for args in some_iterable:
    my_func(*args)  # result is never stored

虽然现在不鼓励 map 的 se 支持列表理解,但它可能会带来一些好处。如果该函数是无状态的,您可以将 map 替换为并行或异步版本;你不能对列表理解或显式循环做同样的事情。然而,对于更小/更简单的情况,这可能有点矫枉过正。

# imagine we have a module providing a thread/process pool
# there is a ton of reference implementations including here on SO
from my_threadlib import map

# ... the rest of code remains unchanged
map(my_func, iterable)    

无论如何,这里的判断是主观的,更多地取决于您的代码风格实践和将要使用它的上下文。

关于当我们不关心输出时,Python 内置习惯用法将函数应用于可迭代对象的每个元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62311774/

相关文章:

python-3.x - OpenCV - Python 将底部添加到现有图像

python - 在 Python 中使用 credstash

c# - Python 到 C# 代码解释

python - 如何将请求响应与请求映射?

python - 连接数据帧时处理极坐标中的空列

python - 如何从命令提示符运行 Pygame 零程序?

python - tkinter unbind 似乎没有取消绑定(bind)

python - 从 Python Dataframe 创建术语频率矩阵

python-3.x - 是否可以通过编程方式使用 pip 安装 python 库?

python - 当 Python 中不再显示唯一 ID 时标记大型数据集