Python dictionary that maps strings to a set of strings?
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()
Fil开发者_开发问答e "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.)
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
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)
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.
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
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 ():
精彩评论