Python:使用itertools将列表分组的参数

5 投票
2 回答
3076 浏览
提问于 2025-04-15 18:12

这是一个关于快速代码的讨论,这种代码使用了标准库,但对我来说有些晦涩难懂,跟自己手动写的代码相比。在这个讨论串(以及其他类似的讨论)中,似乎“Pythonic”的方式是使用itertools来将列表分组,就像下面代码示例中的第一个函数(稍微修改自ΤΖΩΤΖΙΟΥ)那样。

我更喜欢第二个函数的原因是,我能理解它是如何工作的。如果我不需要填充(比如把DNA序列转成密码子),我可以瞬间从记忆中复现它。

使用itertools的速度更快。特别是当我们不想要返回一个列表,或者想要填充最后一个条目时,itertools的速度更快。

还有哪些理由支持使用标准库的解决方案呢?

from itertools import izip_longest

def groupby_itertools(iterable, n=3, padvalue='x'):
    "groupby_itertools('abcde', 3, 'x') --> ('a','b','c'), ('d','e','x')"
    return izip_longest(*[iter(iterable)]*n, fillvalue=padvalue)

def groupby_my(L, n=3, pad=None):
    "groupby_my(list('abcde'), n=3, pad='x') --> [['a','b','c'], ['d','e','x']]"
    R = xrange(0,len(L),n)
    rL = [L[i:i+n] for i in R]
    if pad:
        last = rL[-1]
        x = n - len(last)
        if isinstance(last,list):
            rL[-1].extend([pad] * x)
        elif isinstance(last,str):
            rL[-1] += pad * x
    return rL

计时:

$ python -mtimeit -s 'from groups import groupby_my, groupby_itertools;  L = list("abcdefghijk")' 'groupby_my(L)'
100000 loops, best of 3: 2.39 usec per loop

$ python -mtimeit -s 'from groups import groupby_my, groupby_itertools;  L = list("abcdefghijk")' 'groupby_my(L[:-1],pad="x")'
100000 loops, best of 3: 4.67 usec per loop

$ python -mtimeit -s 'from groups import groupby_my, groupby_itertools;  L = list("abcdefghijk")' 'groupby_itertools(L)'
1000000 loops, best of 3: 1.46 usec per loop

$ python -mtimeit -s 'from groups import groupby_my, groupby_itertools;  L = list("abcdefghijk")' 'list(groupby_itertools(L))'
100000 loops, best of 3: 3.99 usec per loop

编辑:我会在这里更改函数名称(见Alex的回答),但函数太多了,所以我决定发这个警告。

2 个回答

5

花时间学习Python的基础知识将来会大有裨益。因此,记得学习itertools这个模块,以及groupby是怎么工作的。使用itertools通常会比自己手动写的解决方案更快,而且它还能帮助你将来写出更好的代码。

16

当你使用标准库里的工具,而不是自己从头开始编写代码时,你不仅能得到经过优化的软件(有时候效果特别好,比如itertools里的组件),更重要的是,你可以享受到大量的功能,而不需要自己去测试、调试和维护这些功能——你实际上是在利用那些为标准库贡献了测试、调试和维护工作的优秀程序员们的成果!

因此,花时间去了解标准库能给你带来的好处,绝对是值得的,而且回报会很快,甚至会多次回报——你会发现自己能像记住自己写的代码一样轻松记住这些标准库的用法,甚至可能更好,因为你使用了更多的现成工具。

顺便提一下,“分组(group by)”这个词对大多数程序员来说有着明确的、习惯性的意思,因为它在SQL中有这样的用法(在itertools中也类似)。所以我建议你不要把它用在完全不同的事情上——这样只会在你和其他人合作时造成混淆(希望你能多和别人合作,因为单打独斗的“牛仔”程序员时代早已过去了,这也是支持标准化而反对重复造轮子的一个理由;-)。

最后,你的文档字符串和函数的参数顺序不匹配——这是个错误;-)。

撰写回答