Python Словарь Понимание

Можно ли создать понимание словаря в Python (для ключей)?

Без понимания списков вы можете использовать что-то вроде этого:

l = []
for n in range(1, 11):
    l.append(n)

Мы можем сократить это до понимания списка: l = [n for n in range(1, 11)].

Однако, скажем, я хочу установить ключи словаря на одно и то же значение. Я могу сделать:

d = {}
for n in range(1, 11):
     d[n] = True # same value for each

Я пробовал это:

d = {}
d[i for i in range(1, 11)] = True

Однако, я получаю SyntaxError на for.

Кроме того (мне не нужна эта часть, но просто интересно), можете ли вы установить ключи словаря на кучу разных значений, например:

d = {}
for n in range(1, 11):
    d[n] = n

Возможно ли это с пониманием словаря?

d = {}
d[i for i in range(1, 11)] = [x for x in range(1, 11)]

Это также увеличивает значение SyntaxError на for.

Ответ 1

словарные понятия в Python 2.7+, но они не работают так, как вы пытаетесь. Подобно пониманию списка, они создают новый словарь; вы не можете использовать их для добавления ключей к существующему словарю. Кроме того, вы должны указать ключи и значения, хотя, конечно, вы можете указать фиктивное значение, если хотите.

>>> d = {n: n**2 for n in range(5)}
>>> print d
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

Если вы хотите установить для них все значение True:

>>> d = {n: True for n in range(5)}
>>> print d
{0: True, 1: True, 2: True, 3: True, 4: True}

То, что вы, кажется, запрашиваете, - это способ сразу установить сразу несколько ключей на существующий словарь. Для этого нет прямого ярлыка. Вы можете либо зацикливаться, как вы уже показали, либо использовать понимание словаря для создания нового dict с новыми значениями, а затем сделать oldDict.update(newDict), чтобы объединить новые значения в старый dict.

Ответ 2

Вы можете использовать метод класса dict.fromkeys...

>>> dict.fromkeys(range(1, 11), True)
{1: True, 2: True, 3: True, 4: True, 5: True, 6: True, 7: True, 8: True, 9: True, 10: True}

Это самый быстрый способ создания словаря, где все ключи сопоставляются с одним и тем же значением.

Будьте осторожны, используя это с изменяемыми объектами:

d = dict.fromkeys(range(10), [])
d[1].append(2)
print(d[2])  # ???

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

from collections import defaultdict
d = defaultdict(lambda: True)

Чтобы ответить на вторую часть, нужно понять, что вам нужно:

{k: k for k in range(10)}

Или для python2.6:

dict((k, k) for k in range(10))

Вы также можете создать умный подкласс dict, который работает как a defaultdict, если вы переопределите __missing__:

>>> class KeyDict(dict):
...    def __missing__(self, key):
...       #self[key] = key  # Maybe add this also??? 
...       return key
... 
>>> d = KeyDict()
>>> d[1]
1
>>> d[2]
2
>>> d[3]
3
>>> print(d)
{}

Ухоженная.

Ответ 3

>>> {i:i for i in range(1, 11)}
{1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10}

Ответ 4

Мне очень нравится комментарий @mgilson, так как если у вас есть два итератива, один из которых соответствует клавишам, а другой - значениям, вы также можете сделать следующее.

keys = ['a', 'b', 'c']
values = [1, 2, 3]
d = dict(zip(keys, values))

дает

d = {'a': 1, 'b': 2, 'c': 3}

Ответ 5

Используйте dict() в списке кортежей, это решение позволит вам иметь произвольные значения в каждом списке, если они имеют одинаковую длину

i_s = range(1, 11)
x_s = range(1, 11)
# x_s = range(11, 1, -1) # Also works
d = dict([(i_s[index], x_s[index], ) for index in range(len(i_s))])

Ответ 6

Рассмотрим этот пример подсчета появления слов в списке, используя понимание словаря

my_list = ['hello', 'hi', 'hello', 'today', 'morning', 'again', 'hello']
my_dict = {k:my_list.count(k) for k in my_list}
print(my_dict)

И результат

{'again': 1, 'hi': 1, 'hello': 3, 'today': 1, 'morning': 1}

Ответ 7

Основной целью понимания списка является создание нового списка на основе другого без изменения или уничтожения исходного списка.

Вместо записи

    l = []
    for n in range(1, 11):
        l.append(n)

или

    l = [n for n in range(1, 11)]

вы должны написать только

    l = range(1, 11)

В двух верхних блоках кода вы создаете новый список, итерации через него и просто возврат каждого элемента. Это просто дорогой способ создания копии списка.

Чтобы получить новый словарь со всеми ключами, установленными на одно и то же значение на основе другого dict, сделайте следующее:

    old_dict = {'a': 1, 'c': 3, 'b': 2}
    new_dict = { key:'your value here' for key in old_dict.keys()}

Вы получаете SyntaxError, потому что, когда вы пишете

    d = {}
    d[i for i in range(1, 11)] = True

вы в основном говорите: "Установите мой ключ" я для я в диапазоне (1, 11) "True" и "i for я in range (1, 11)" не является допустимым ключом, это просто ошибка синтаксиса. Если dicts поддерживает списки как ключи, вы бы сделали что-то вроде

    d[[i for i in range(1, 11)]] = True

а не

    d[i for i in range(1, 11)] = True

но списки не хешируются, поэтому вы не можете использовать их в качестве ключей dict.

Ответ 8

вы не можете хешировать список. попробуйте это вместо этого, он использует кортежи

d[tuple([i for i in range(1,11)])] = True