Привет! Запускаю раздел Fast Python, в котором буду делиться простыми рецептами про то, как ускорить и оптимизировать выполнение кода на Python.
Первый выпуск будет посвящен обновлению данных в словарях. Словари - одни из найболее часто используемых типов данных в Python. И сколько времени я с ними не работаю, у меня никогда не возникал вопрос как правильней обновить данные в словаре. Я для себя всегда отвечал на него, что правильней обновлять используя метод update
, но сегодня с утра наткнулся на твит от Брэда Монтгомери и мой мир изменился.
Оказывается, что более правильным с точки зрения скорости является обновление словаря через поочередное присваивание значений, чем единичный апдейт. Не верите? Результаты замеров весьма красноречивы:
Python 3.4.3
In [2]: timeit("d = {}; d.update({'first': 'first', 'second': ['one', 'two', 'three'], 'third': True})", number=1000000)
Out[2]: 0.9664371280086925
In [3]: timeit("d = {}; d['first'] = 'first'; d['second'] = ['one', 'two', 'three']; d['third'] = True", number=1000000)
Out[3]: 0.4200690069992561
Python 2.7.9
In [2]: timeit("d = {}; d.update({'first': 'first', 'second': ['one', 'two', 'three'], 'third': True})", number=1000000)
Out[2]: 1.0035829544067383
In [3]: timeit("d = {}; d['first'] = 'first'; d['second'] = ['one', 'two', 'three']; d['third'] = True", number=1000000)
Out[3]: 0.5186400413513184
Bonus: PyPy 2.4.0
>>>> timeit("d = {}; d.update({'first': 'first', 'second': ['one', 'two', 'three'], 'third': True})", number=1000000)
0.10811400413513184
>>>> timeit("d = {}; d['first'] = 'first'; d['second'] = ['one', 'two', 'three']; d['third'] = True", number=1000000)
0.005925893783569336
Итого: Если вы где-то в коде увидите обновление одиночного или множественных элементов словаря через .update
- смело переписывайте этот фрагмент на использование __setitem__
.
Fast Python:
data['key'] = 'value'
data['another-key'] = 'another-value'
Slow Python:
data.update({
'key': 'value',
'another-key': 'another-value',
})
UPD: Михаил Кривушин (deepwalker) в комментариях объяснил почему так происходит:
По дороге создается еще один словарь, и потом уже из него копируются элементы
https://gist.github.com/Deepwalker/c52a74c26df0707dd303
UPD2: Если ключи словаря не используют специальных символов и являются валидными Python ключами, то лучше использовать синтаксис .update(key='value')
, вместо .update({'key': 'value'})
:
Python 3.4.3
In [2]: timeit("d = {}; d.update(first='first', second=['one', 'two', 'three'], third=True)", number=1000000)
Out[2]: 0.88018084000214
Python 2.7.9
In [2]: timeit("d = {}; d.update(first='first', second=['one', 'two', 'three'], third=True)", number=1000000)
Out[2]: 0.7820448875427246
PyPy 2.4.0
>>>> timeit("d = {}; d.update(first='first', second=['one', 'two', 'three'], third=True)", number=1000000)
0.010169029235839844