2010-01-19 12 views
5

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.

+1

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

Odpowiedz

15

Kiedy ponownie używasz narzędzi ze standardowej biblioteki, zamiast "wymyślać koło", kodując je samemu od podstaw, nie tylko otrzymujesz dobrze zoptymalizowane i dostrojone oprogramowanie (czasami zadziwiająco, jak często w przypadku Komponenty itertools: ważniejsze jest to, że uzyskujesz dużą liczbę funkcji, których nie musisz testować, debugować i utrzymywać - wykorzystujesz wszystkie testy, debugowanie i prace konserwacyjne wielu wspaniałych programistów, którzy przyczyniają się do standardowa biblioteka!

Inwestycja w zrozumienie, co oferuje standardowa biblioteka, spłaca się więc szybko i wielokrotnie - i będziesz w stanie "odtworzyć z pamięci" tak samo dobrze jak na nowo utworzony kod koła, a nawet lepiej dzięki większej ilości ponownego wykorzystania.

Nawiasem mówiąc, termin "grupa po" ma dobrze zdefiniowane, idiomatyczne znaczenie dla większości programistów, dzięki zastosowaniu w SQL (i podobnym zastosowaniu w samym itertools): sugerowałbym, aby unikać używania go dla coś zupełnie innego - to tylko wywoła zamieszanie za każdym razem, gdy współpracujesz z kimś innym (miejmy nadzieję, że często, odkąd rozkwit solowego, "kowboja" programisty już dawno minął - kolejny argument przemawiający za normami i odradzaniem się kół ;-).

Wreszcie Twój docstring nie pasuje do podpisu swoich funkcjach - błąd argumenty rzędu ;-).

+0

+1 Ponadto, nawet osoba, która faktycznie coś kodowała może być zdezorientowana, gdy spojrzą na nią za rok. – balpha

+0

Dzięki, Alex.Właściwie "moja" funkcja to ta bez docstrowania :) Naprawię drugą. – telliott99

5

Czas spędzony na poznawaniu podstaw Pythona spłaci się później. Dlatego ucz się itertools i jak działa groupby. Nie tylko używa on narzędzi itertools, które prawdopodobnie będą szybsze niż jakiekolwiek ręcznie zwijane rozwiązania, ale pomoże Ci w napisaniu lepszego kodu w przyszłości.

Powiązane problemy