#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