Является ли параметр defaultdict в модуле Python более быстрым, чем использование setdefault? - программирование
Подтвердить что ты не робот

Является ли параметр defaultdict в модуле Python более быстрым, чем использование setdefault?

Я видел, как другие программисты Python использовали defaultdict из модуля коллекций для следующего использования:

from collections import defaultdict

s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]

def main():
    d = defaultdict(list)
    for k, v in s:
        d[k].append(v)

Я обычно подходил к этой проблеме, используя вместо этого setdefault:

def main():
    d = {}
    for k, v in s:
        d.setdefault(k, []).append(v)

Фактически документы утверждают, что использование defaultdict выполняется быстрее, но я видел, что обратное было верно при тестировании себя:

$ python -mtimeit -s "from withsetdefault import main; s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)];" "main()"
100000 loops, best of 3: 4.51 usec per loop
$ python -mtimeit -s "from withdefaultdict import main; s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)];" "main()"
100000 loops, best of 3: 5.38 usec per loop

Что-то не так с тем, как я настроил тесты?

Для справки, я использую Python 2.7.3 [GCC 4.2.1 (Apple Inc. build 5666)

4b9b3361

Ответ 1

Да, есть что-то "неправильное":

Вы положили создание (default)dict в инструкцию вместо установки. Построение нового defaultdict дороже обычного dict, и обычно это не узкое место, которое вы должны профилировать в программе. В конце концов, вы создаете свои структуры данных один раз, но вы используете их много раз.

Если вы выполните свои тесты, как показано ниже, вы увидите, что операции defaultdict выполняются быстрее:

>>> import timeit
>>> setup1 = """from collections import defaultdict
... s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
... d = defaultdict(list)"""
>>> stmt1 = """for k, v in s:
...     d[k].append(v)"""
>>> setup2 = """s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
... d = {}"""
>>> stmt2 = """for k, v in s:
...     d.setdefault(k, []).append(v)"""
>>> timeit.timeit(setup=setup1, stmt=stmt1)
1.0283400125194078
>>> timeit.timeit(setup=setup2, stmt=stmt2)
1.7767367580925395

Python 2.7.3 на Win7 x64.