Python dictionary that maps strings to a set of strings?

好久不见. 提交于 2019-12-21 07:05:11

问题


I would like to be able to make a Python dictionary with strings as keys and sets of strings as the values. E.g.: { "crackers" : ["crunchy", "salty"] } It must be a set, not a list.

However, when I try the following:

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

I get:

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'

If I do this:

  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

I get:

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

Any tips on how to coerce Python into doing what I'd like? I'm an intermediate Python user (or so I thought, until I ran into this problem.)


回答1:


set.add() does not return a new set, it modifies the set it is called on. Use it this way:

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

Also, if you use a for loop to iterate over a dict, you are iterating over the keys:

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

Alternatively you could iterate over word_dict.items() or word_dict.iteritems():

for key, value in word_dict.items():
   print key, value



回答2:


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)



回答3:


When you say word_dict["foo"].add("baz"), you are adding 'baz' to the set word_dict["foo"].

The function returns None -- updating the set is a side-effect. So

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

ultimately sets word_dict["foo"] to None.

Just word_dict["foo"].add("baz") would be correct.

In the second scenario, when you say

for key, value in word_dict:                                                       

you run into an error because the correct syntax is

for key in word_dict: 

to loop over just the keys in word_dict. In this situation, you want

for key,value in word_dict.iteritems(): 

instead.




回答4:


Try:

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]

It looks like standard dictionary iterator returns only key but not tuple.

Proof:

>>> 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



回答5:


The problem is this:

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

When you call word_dict["foo"].add("baz"), you're mutating the set that word_dict["foo"] refers to, and that operation returns None. So reading your statement right to left, you're adding "baz" to the set refered to by word_dict["foo"], and then setting the result of that operation (that is, None) to word_dict["foo"].

So, to make this work as you expect, just remove word_dict["foo"] = from your statement.

Dictionaries iterate on their keys by default, hence the ValueError you try this:

for key, value in word_dict: 

What's happening here is that iterating on word_dict is returning a key only (say, "foo"), which you're then trying to unpack into the variables key & value. Unpacking "foo" gives you "f", "o", & "o", which is one value too many to fit into two variables, and hence your ValueError.

As others have stated, what you want is to iterate on the dictionary's key-value pairs, like so:

for key, value in word_dict.iteritems (): 


来源:https://stackoverflow.com/questions/2285874/python-dictionary-that-maps-strings-to-a-set-of-strings

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!