Представьте, что у вас есть:
keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')
Какой самый простой способ создать следующий словарь?
dict = {'name' : 'Monty', 'age' : 42, 'food' : 'spam'}
Наиболее производительный - Python 2.7 и 3, понимание слова:
Возможным улучшением при использовании конструктора dict является использование собственного синтаксиса понимания dict (не списочного понимания, как его ошибочно выразили другие):
new_dict = {k: v for k, v in zip(keys, values)}
В Python 2 zip
возвращает список, чтобы избежать создания ненужного списка, используйте вместо него izip
(псевдоним zip может уменьшить изменения кода при переходе на Python 3).
from itertools import izip as zip
Так что еще:
new_dict = {k: v for k, v in zip(keys, values)}
Python 2, идеально подходит для <= 2,6 </h2>
izip
из itertools
становится zip
в Python 3. izip
лучше, чем zip для Python 2 (потому что он избегает ненужного создания списка), и идеально подходит для 2.6 или ниже:
from itertools import izip
new_dict = dict(izip(keys, values))
Python 3
В Python 3 zip
становится той же функцией, что была в модуле itertools
, так что это просто:
new_dict = dict(zip(keys, values))
Тем не менее, понимание речи было бы более производительным (см. Обзор производительности в конце этого ответа).
Результат для всех случаев:
Во всех случаях:
>>> new_dict
{'age': 42, 'name': 'Monty', 'food': 'spam'}
Пояснение:
Если мы посмотрим на справку по dict
, то увидим, что она принимает различные формы аргументов:
>>> help(dict)
class dict(object)
| dict() -> new empty dictionary
| dict(mapping) -> new dictionary initialized from a mapping object's
| (key, value) pairs
| dict(iterable) -> new dictionary initialized as if via:
| d = {}
| for k, v in iterable:
| d[k] = v
| dict(**kwargs) -> new dictionary initialized with the name=value pairs
| in the keyword argument list. For example: dict(one=1, two=2)
Оптимальный подход - использовать итерацию, избегая создания ненужных структур данных. В Python 2 zip создает ненужный список:
>>> zip(keys, values)
[('name', 'Monty'), ('age', 42), ('food', 'spam')]
В Python 3 эквивалент будет:
>>> list(zip(keys, values))
[('name', 'Monty'), ('age', 42), ('food', 'spam')]
и Python 3 zip
просто создают итеративный объект:
>>> zip(keys, values)
<zip object at 0x7f0e2ad029c8>
Поскольку мы хотим избежать создания ненужных структур данных, мы обычно хотим избегать Python 2 zip
(так как он создает ненужный список).
Менее производительные альтернативы:
Это выражение генератора передается конструктору dict:
generator_expression = ((k, v) for k, v in zip(keys, values))
dict(generator_expression)
или эквивалентно:
dict((k, v) for k, v in zip(keys, values))
И это понимание списка, передаваемое конструктору dict:
dict([(k, v) for k, v in zip(keys, values)])
В первых двух случаях дополнительный слой неоперативных (следовательно, ненужных) вычислений помещается поверх итерируемой zip, а в случае понимания списка дополнительный список создается без необходимости. Я ожидал бы, что все они будут менее производительными и, конечно, не более.
Обзор производительности:
В 64-битном Python 3.4.3, в Ubuntu 14.04, упорядочено от самого быстрого до самого медленного:
>>> min(timeit.repeat(lambda: {k: v for k, v in zip(keys, values)}))
0.7836067057214677
>>> min(timeit.repeat(lambda: dict(zip(keys, values))))
1.0321204089559615
>>> min(timeit.repeat(lambda: {keys[i]: values[i] for i in range(len(keys))}))
1.0714934510178864
>>> min(timeit.repeat(lambda: dict([(k, v) for k, v in zip(keys, values)])))
1.6110592018812895
>>> min(timeit.repeat(lambda: dict((k, v) for k, v in zip(keys, values))))
1.7361853648908436