gpt4 book ai didi

python - 索引效率的迭代子集

转载 作者:太空宇宙 更新时间:2023-11-04 00:04:36 25 4
gpt4 key购买 nike

我正在尝试根据另一个索引列表遍历列表中的元素子集。

最短/最 pythonic 的方式似乎会使用列表理解来达到以下效果:

    for elt in [lst[idx] for idx in idxs]:
elt.do_stuff()
elt.do_more_stuff()

但我无法摆脱这种感觉,如果我要循环很多次,每次都重建列表理解可能会很昂贵,我应该多花一行来写:

    for idx in indxs:
elt = lst[idx]
elt.do_stuff()
elt.do_more_stuff()

对 python 及其相对效率/低效率有更多了解的人能否了解这些方法之间的实际计算成本差异?我知道,我知道这两种方式都可能工作得很好,但一旦我开始想知道其中的区别,我就很好奇了。

最佳答案

你的第二个循环很好,但你的第一个循环可以在不构建临时 list 的情况下工作通过使用 a generator expression :

for elt in (lst[idx] for idx in idxs):
elt.do_stuff()
elt.do_more_stuff()

或者(如果有很多索引,可能会稍微快一些)(ab?)使用 map :

for elt in map(lst.__getitem__, idxs):
elt.do_stuff()
elt.do_more_stuff()

在这两种情况下(至少在 Py3 上,map 返回一个迭代器,而不是一个新的 list ),效果是懒惰地查找每个索引作为下一个 elt被要求;它并不急于制作 list在循环甚至开始之前。

如果您要重复查找同一组索引(即 idxs 不变),您可能会考虑另一种选择。你可以创建一个 operator.itemgetter一旦在前面,然后使用它。它会急切地运行(就像 list 理解),但它会:

  1. 返回 tuple而不是 list (稍微更高效的内存和更好的内存局部性,但通常没有什么有意义的区别)
  2. 推楼说tuple ,从头到尾,一直到C层,其中一个list理解,虽然使用专门的字节码,仍然必须在常规解释器中完成所有工作,至少在 CPython 上比大多数推到 C 上的工作慢

对于这种方法,您需要:

# Done once up front
from operator import itemgetter
getidxs = itemgetter(*idxs) # Note: Will fail if idxs is not at least length 2; won't return tuple when getting one item

# Done every time
for elt in getidxs(lst):
elt.do_stuff()
elt.do_more_stuff()

您需要分析以确定:

  1. 是否真的需要任何这种优化
  2. 哪种解决方案对您最有意义(像 itemgetter 这样的急切解决方案和 listcomp 使用更多内存,但可能运行得更快;惰性解决方案具有固定且较小的内存开销,但可能运行得更慢)

关于python - 索引效率的迭代子集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54585130/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com