Python словарь, который отображает строки в набор строк? - PullRequest
15 голосов
/ 18 февраля 2010

Я хотел бы иметь возможность сделать словарь Python со строками в качестве ключей и наборов строк в качестве значений. Например: { "crackers" : ["crunchy", "salty"] } Это должен быть набор, а не список.

Однако, когда я пытаюсь сделать следующее:

  word_dict = dict()
  word_dict["foo"] = set()
  word_dict["foo"] = word_dict["foo"].add("baz")                                    
  word_dict["foo"] = word_dict["foo"].add("bang")

Я получаю:

Traceback (most recent call last):
  File "process_input.py", line 56, in <module>
    test()
  File "process_input.py", line 51, in test
    word_dict["foo"] = word_dict["foo"].add("bang")
AttributeError: 'NoneType' object has no attribute 'add'

Если я сделаю это:

  word_dict = dict()
  myset = set()
  myset.add("bar")
  word_dict["foo"] = myset
  myset.add("bang")
  word_dict["foo"] = myset

  for key, value in word_dict:                                                       
      print key,                                                                
      print value

Я получаю:

Traceback (most recent call last):
  File "process_input.py", line 61, in <module>
    test()
  File "process_input.py", line 58, in test
    for key, value in word_dict:
ValueError: too many values to unpack

Какие-нибудь советы о том, как заставить Python делать то, что я хотел бы? Я промежуточный пользователь Python (или я так думал, пока не столкнулся с этой проблемой).

Ответы [ 5 ]

28 голосов
/ 18 февраля 2010

set.add() не возвращает новый set, он изменяет set, который вызывается. Используйте это так:

word_dict = dict()
word_dict["foo"] = set()
word_dict["foo"].add("baz")                                    
word_dict["foo"].add("bang")

Кроме того, если вы используете цикл for для итерации по dict, вы итерируете по ключам:

for key in word_dict:
   print key, word_dict[key]

В качестве альтернативы вы можете перебрать word_dict.items() или word_dict.iteritems():

for key, value in word_dict.items():
   print key, value
26 голосов
/ 18 февраля 2010
from collections import defaultdict

word_dict = defaultdict(set)
word_dict['banana'].add('yellow')
word_dict['banana'].add('brown')
word_dict['apple'].add('red')
word_dict['apple'].add('green')
for key,values in word_dict.iteritems():
    print "%s: %s" % (key, values)
6 голосов
/ 18 февраля 2010

Когда вы говорите word_dict["foo"].add("baz"), вы добавляете 'baz' к набору word_dict ["foo"].

Функция возвращает None - обновление набора является побочным эффектом. Итак

word_dict["foo"] = word_dict["foo"].add("baz") 

в конечном итоге устанавливает word_dict["foo"] на None.

Просто word_dict["foo"].add("baz") будет правильным.

Во втором сценарии, когда вы говорите

for key, value in word_dict:                                                       

вы столкнулись с ошибкой, потому что правильный синтаксис -

for key in word_dict: 

для циклического перебора только ключей в word_dict. В этой ситуации вы хотите

for key,value in word_dict.iteritems(): 

вместо.

1 голос
/ 18 февраля 2010

Проблема заключается в следующем:

word_dict["foo"] = word_dict["foo"].add("baz")   

Когда вы вызываете word_dict["foo"].add("baz"), вы изменяете набор, к которому относится word_dict["foo"], и эта операция возвращает None. Таким образом, читая ваше утверждение справа налево, вы добавляете «baz» к набору, на который ссылается word_dict["foo"], а затем устанавливаете результат этой операции (то есть None) на word_dict["foo"].

Итак, чтобы сделать это так, как вы ожидаете, просто удалите word_dict["foo"] = из вашего заявления.

Словари итерируют свои ключи по умолчанию, поэтому ValueError вы пытаетесь сделать так:

for key, value in word_dict: 

Здесь происходит то, что итерация по word_dict возвращает только ключ (скажем, "foo"), который вы затем пытаетесь распаковать в переменные key & value. Распаковка "foo" дает вам "f", "o", & "o", что на одно значение слишком много, чтобы поместиться в две переменные, и, следовательно, ваш ValueError.

Как уже говорили другие, вам нужно перебирать пары ключ-значение словаря, например:

for key, value in word_dict.iteritems (): 
1 голос
/ 18 февраля 2010

Попробуйте:

word_dict = dict()
myset = set()
myset.add("bar")
word_dict["foo"] = myset
myset.add("bang")
word_dict["foo"] = myset

for key in word_dict:                                                       
    print key, word_dict[key]

Похоже, что стандартный итератор словаря возвращает только key, но не кортеж.

Доказательство:

>>> d = { 'test': 1 }
>>> for k, v in d: print k, v
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack
>>> for k in d: print d[k]
... 
1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...