Понимание словаря Python

#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. Для информации будущих читателей: массивы NumPy позволяют вам присваивать нескольким элементам одно значение или список значений, как вы пытаетесь сделать. Хотя, если у вас еще нет причин использовать NumPy, вероятно, оно того не стоит только для этой функции.

Ответ №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.

Комментарии:

1. FWIW, dict.update также может принимать итерацию пар ключ-значение, как dict и конструктор

2. Обратите внимание, что если вы хотите создать словарь со всеми одинаковыми значениями, используйте dict.fromkeys() . Итак, чтобы установить все значения True , используйте dict.fromkeys(range(5), True) . Будьте осторожны, значение не копируется , поэтому вы можете избежать этого, если у вас есть изменяемое значение; оно будет общим для всех ключей.

3. Примечание: ключи также могут быть результатом метода : { n*2 : n for n in range(3) } => {0: 0, 2: 1, 4: 2} . Оба могут быть выполнены в одном и том же выражении : { n*2 : n*3 for n in range(3) } => { 0: 0, 2: 3, 4: 6 } .

Ответ №2:

Вы можете использовать метод 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]} !!!
 

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

 from collections import defaultdict
d = defaultdict(True)
 

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

 {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)
{}
 

Комментарии:

1. Обратите внимание, что в случае d = defaultdict(lambda: True) , лямбда-выражение не требуется, поскольку True является (или не должно) изменяемым.

Ответ №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:

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

 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}
 

Комментарии:

1. Это интересно, хотя и не самое эффективное, поскольку вы будете считать ключи, такие как «привет», несколько раз

2. Имейте в виду, что это O (N ^ 2) и невероятно медленно даже для небольших размеров данных. Я добавил его в некоторый производственный код, и это было огромным узким местом. tbh этот ответ опасен, имейте в виду.

Ответ №6:

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

Комментарии:

1. В качестве примечания, это то же самое, что d = dict(zip(i_s,x_s))

Ответ №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()}
 

Вы получаете синтаксическую ошибку, потому что, когда вы пишете

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

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

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

и не

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

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

Ответ №8:

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

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

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

 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 , чтобы убедиться, что вы используете правильное имя пользователя для их ввода.

Ответ №9:

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

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