有效使用Python列表推导

时间:2012-10-05 18:42:51

标签: python list-comprehension

我有一个可能很长的Python对象列表。在特定时间,我对列表中具有某个属性(例如flag)的所有元素感兴趣,这些元素的计算结果为False。为此,我一直在使用列表理解,如下所示:

objList = list()
# ... populate list
[x for x in objList if not x.flag]

这似乎运作良好。在形成子列表之后,我可能需要执行一些不同的操作:

  1. 下标子列表以获取索引ind的元素。
  2. 计算子列表的长度(即具有flag == False的元素数量。)
  3. 在子列表中搜索特定对象的第一个实例(即使用列表的.index()方法)。
  4. 我使用简单形成子列表的简单方法实现了这些,然后使用其方法获取我想要的数据。我想知道是否有更有效的方法来解决这些问题。 #1和#3至少看起来似乎可以进行优化,因为在#1中我只需要子列表的第一个ind + 1匹配元素,不一定是整个结果集,而在#3中我只需要搜索通过子列表,直到找到匹配的元素。

    有一个好的Pythonic方法吗?我猜我可能以某种方式使用()语法来获取生成器而不是创建整个列表,但我还没有以正确的方式发生。我显然可以手动编写循环,但我正在寻找像基于理解的方法一样优雅的东西。

3 个答案:

答案 0 :(得分:2)

如果您需要多次执行这些操作,其他方法的开销会更高,列表是最好的方法。它也可能是最清晰的,所以如果内存不是问题,那么我建议你继续使用它。

如果内存/速度有问题,那么还有其他选择 - 请注意,速度方面,这些可能实际上较慢,具体取决于软件的常见情况。

对于您的方案:

#value = sublist[n]
value = nth(x for x in objList if not x.flag, n)

#value = len(sublist)
value = sum(not x.flag for x in objList)

#value = sublist.index(target)
value = next(dropwhile(lambda x: x != target, (x for x in objList if not x.flag)))

使用itertools文档中的itertools.dropwhile()the nth() recipe

答案 1 :(得分:1)

我会假设你可以做这三件事中的任何一件事,你可能不止一次这样做。

在这种情况下,你想要的基本上是写一个懒惰的评估列表类。它将保留两个数据,一个真实的 list缓存的评估项目,以及其余的生成器。然后,您可以执行ll[10],它会评估最后一个项目ll.index('spam'),它会进行评估,直到找到'spam',然后len(ll)并评估其余项目列表中的所有内容都在真实列表中缓存它所看到的内容,因此不会执行任何操作。

构建它看起来像这样:

LazyList(x for x in obj_list if not x.flag)

但是在你真正开始使用它之前,实际上不会计算任何东西。

答案 2 :(得分:1)

由于您评论说您的objList可以更改,如果您需要索引或搜索objList本身,那么您最好只存储两个不同的列表,一个使用.flag = True,使用.flag = False。然后,您可以直接使用第二个列表,而不是每次都使用列表推导构建它。

如果这适用于您的情况,则可能是最有效的方法。