Как сделать словарь из двух списков в Python (ключи и значения)?
У меня есть отдельно список ключей и отдельно список значений, и я хочу склеить их в словарь, где первый элемент ключей это первый ключ и так далее. Как это сделать без ручного цикла? Слышал про zip.
2 ответа
Идеальный инструмент — zip плюс конструктор dict. zip спаривает элементы по позициям, а dict собирает из пар словарь:
keys = ['имя', 'возраст', 'город']
values = ['Аня', 30, 'Москва']
d = dict(zip(keys, values))
# {'имя': 'Аня', 'возраст': 30, 'город': 'Москва'}
zip(keys, values) создаёт пары ('имя', 'Аня'), ('возраст', 30), ..., а dict() превращает их в словарь.
Важный нюанс — если списки разной длины, zip тихо обрежет по короткому, без ошибки:
dict(zip(['a', 'b', 'c'], [1, 2])) # {'a': 1, 'b': 2} — c потерялся
Это частый источник незаметных багов: проверяйте, что len(keys) == len(values), если оба должны совпадать.
Если среди ключей есть повторы, в словаре останется только последнее значение для такого ключа (ключи уникальны):
dict(zip(['a', 'a', 'b'], [1, 2, 3])) # {'a': 2, 'b': 3}
И помните: ключами могут быть только хешируемые объекты (строки, числа, кортежи). Если в keys окажется список, будет TypeError: unhashable type.
zip удобен и для обратной задачи — распаковки: keys, values = zip(*d.items()).
То же можно сделать генератором словаря, если попутно нужна обработка:
d = {k: v for k, v in zip(keys, values)}
Голый dict(zip(...)) короче, но генератор удобен, когда надо, например, пропустить часть пар или преобразовать значения: {k: int(v) for k, v in zip(keys, values)}. Под капотом всё тот же zip, просто с возможностью вставить условие или функцию.