To jest pytanie o względnych zalet szybkiego kodu, który korzysta z biblioteki standardowej, ale jest niejasne (przynajmniej dla mnie) versus ręcznie walcowane alternatywy. W tym thread (i innych, które duplikuje), wydaje się, że "Pythonicznym" sposobem podziału listy na grupy jest użycie itertools, jak w pierwszej funkcji w poniższym przykładzie kodu (zmodyfikowanym nieznacznie od ΤΖΩΤΖΙΟΥ).Python: argumenty za korzystanie itertools podzielić listę na grupy
Powodem, dla którego wolę drugą funkcję, jest to, że mogę zrozumieć, jak to działa, i jeśli nie potrzebuję dopełnienia (zamieniając sekwencję DNA w kodony, powiedzmy), mogę odtworzyć ją z pamięci w jednej chwili.
Szybkość jest lepsza dzięki itertools. W szczególności, jeśli nie chcemy, aby lista była z powrotem, lub chcemy umieścić ostatni wpis, itertools jest szybszy.
Jakie są inne argumenty przemawiające za rozwiązaniem standardowej biblioteki?
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
rozrządu:
$ 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
Edit: Chciałbym tu zmienić nazwy funkcji (patrz odpowiedź Alexa), ale istnieje tak wiele postanowiłem zamiast pisać to ostrzeżenie.
Otrzymałem odpowiedź, której się spodziewałem, tak myślę. Dzięki. Byłoby łatwiej połknąć (jak w mamie mówiącym, żebym jadł mój szpinak), gdybym mógł spojrzeć na * [iter (iterable)] * n i zrozumieć, co robi. Ale biorąc pod uwagę, że docstring jest zawsze dobrym pomysłem, przypuszczam, że użycie itertools jest odpowiednio udokumentowane w kodzie. Z pewnością doceniam pracę eksperta, która trafiła do standardowej biblioteki. – telliott99