Понимание словаря 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,

9 ответов

Решение

В 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.fromkeys метод класса...

>>> dict.fromkeys(range(5), True)
{0: True, 1: True, 2: True, 3: True, 4: True}

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

Но не используйте это с изменяемыми объектами:

d = dict.fromkeys(range(5), [])
# {0: [], 1: [], 2: [], 3: [], 4: []}
d[1].append(2)
# {0: [2], 1: [2], 2: [2], 3: [2], 4: [2]} !!!

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

from collections import defaultdict
d = defaultdict(True)

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

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

Вы, вероятно, не должны этого делать, но вы также можете создать подкласс dict который работает чем-то вроде 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)
{}
>>> {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}

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

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

дающий

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

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

Вместо того чтобы писать

    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

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

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

и не

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

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

Рассмотрим этот пример подсчета вхождения слов в список с использованием словарного понимания.

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}

Используйте 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))])

Понимание словаря очень похоже на понимание списка , но мы получаем словарь в его конце, поэтому нам нужно назначать пары ключ-значение, а не только значения.

Допустим, у нас есть список пользователей, в котором информация о каждом пользователе хранится в виде кортежа. Итак, у нас есть список с четырьмя пользовательскими кортежами. Внутри у них есть идентификатор, уникальный идентификационный номер для каждого пользователя, имя пользователя и пароль.

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

      users = [
    (0, "Bob", "password"),
    (1, "code", "python"),
    (2, "Stack", "overflow"),
    (3, "username", "1234"),
]

username_mapping = {user[1]: user for user in users}
userid_mapping = {user[0]: user for user in users}

print(username_mapping)

"""
Why can this be helpful?

Well, imagine you know a user's username,and you want to get their information out.
You just access, let's say, "Bob," in your username_mapping, and you've got the information out.
"""
print(username_mapping["Bob"])  # (0, "Bob", "password")

# -- Can be useful to log in for example --

username_input = input("Enter your username: ")
password_input = input("Enter your password: ")

_, username, password = username_mapping[username_input]

if password_input == password:
    print("Your details are correct!")
else:
    print("Your details are incorrect.")

Итак, это пример выполнения какого-то входа в систему с использованием этой структуры здесь, этого понимания словаря.

Это действительно полезно, потому что избавляет вас от необходимости выполнять здесь еще один цикл for, чтобы убедиться, что вы используете правильное имя пользователя для их ввода.

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

d[tuple([i for i in range(1,11)])] = True
Другие вопросы по тегам