Python: аргументы для использования itertools для разделения списка на группы - PullRequest
5 голосов
/ 19 января 2010

Это вопрос об относительных достоинствах быстрого кода, который использует стандартную библиотеку, но неясен (по крайней мере для меня) по сравнению с альтернативой, созданной вручную. В этом потоке (и других, которые он дублирует), кажется, что "Pythonic" способ разделить список на группы - это использовать itertools, как в первой функции в примере кода ниже (немного измененном из ΤΖΩΤΖΙΟΥ ).

Причина, по которой я предпочитаю вторую функцию, заключается в том, что я могу понять, как она работает, и если мне не нужно заполнение (например, превращение последовательности ДНК в кодоны), я могу воспроизвести ее из памяти в одно мгновение.

Скорость лучше с 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

Редактировать: Я бы изменил здесь имена функций (см. Ответ Алекса), но их так много, что я решил вместо этого опубликовать это предупреждение.

Ответы [ 2 ]

15 голосов
/ 19 января 2010

Когда вы повторно используете инструменты из стандартной библиотеки, а не «изобретаете колесо», кодируя их с нуля, вы получаете не только хорошо оптимизированное и настроенное программное обеспечение (иногда удивительно, как это часто бывает в случае *). 1001 * компоненты): что более важно, вы получаете большое количество функций, которые вам не нужно тестировать, отлаживать и обслуживать самостоятельно - вы используете всю работу по тестированию, отладке и обслуживанию многих замечательных программистов, которые вносят свой вклад в стандартная библиотека!

Таким образом, инвестиции в понимание того, что предлагает вам стандартная библиотека, окупаются быстро и во много раз - и вы сможете «воспроизводить из памяти» так же, как и для кода заново изобретенного колеса, действительно, вероятно, лучше благодаря на большее количество повторного использования.

Кстати, термин "группа по" имеет четко определенное идиоматическое значение для большинства программистов благодаря его использованию в SQL (и аналогичному использованию в самом itertools): поэтому я бы предложил вам избегать его использования для чего-то совершенно другого - это только порождает путаницу, когда вы сотрудничаете с кем-либо еще (надеюсь, часто, с расцвета сольного, «ковбойского» программиста давно прошло - еще один аргумент в пользу стандартов и против колеса) переосмысление; -)

.

Наконец, ваша строка документации не соответствует сигнатуре вашей функции - ошибка порядка аргументов; -).

5 голосов
/ 19 января 2010

Время, потраченное на изучение основ Python, окупится позже.Поэтому изучите itertools, и как работает groupby.Мало того, что использование itertools может быть быстрее, чем любые ручные решения, это поможет вам написать лучший код в будущем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...