Probably, people
is a dictionary that maps tuples for other data:
>>> people = {("Obama", "Barack"):"USA", ("Roussef", "Dilma"):"BRA"}
>>> for last, first in people:
... print(last, first, people[last, first])
...
Roussef Dilma BRA
Obama Barack USA
If you are not familiar with tuples, the data type tuple
it’s like a list, only unchangeable:
x = (10, 20, 30)
y = ()
z = (10,) # Aqui a vírgula é obrigatória, pra não se confundir com 10 entre parênteses
What makes things confusing is that the Python syntax accepts that you omit the parentheses if the tuple has 2 or more elements:
x = 10, 20, 30
That is to say, people[last, first]
is the same as people[(last, first)]
.
On the type of data people
, I deduced it was a dict
because it’s the only way that code makes sense. Arrays (lists) only allow you to index by number, not by tuples, so people
is not an array. Already an dict
allows tuples as keys, and as the for
applied to a dictionary iterates over its keys, I imagined that this was the right data structure.
By the way, you can iterate over lists/tuples and their indexes or dictionaries and their values using enumerate
and items
, respectively:
>>> lista = [10, 20, 30]
>>> for indice, valor in enumerate(lista):
... print(indice, valor)
...
0 10
1 20
2 30
>>> person = {"Name": "Barack", "Surname": "Obama"}
>>> for chave, valor in person.items():
... print(chave, valor)
...
Name Barack
Surname Obama
These examples work because so much enumerate
how much items
tuples return. This way, one can make a destructuring assignment (or destructuring bind) of its values to a set of other variables:
x, y = 10, 20 # destructuring assignment: x recebe 10, y recebe 20
for x, y in [(10, 20), (30, 40)]: # destructuring bind: para cada tupla t da lista
... # x recebe t[0] e y recebe t[1]
Finally, we come to your "strange" error message: "Too Many values to unpack" means you tried to make a destructuring Bing where there were more values on the right side than on the left:
>>> x, y, z = 10, 20
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: need more than 2 values to unpack
>>> x, y, z = 10, 20, 30 # OK
>>> x, y, z = 10, 20, 30, 40
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 3)
And how did that happen? Simple, in your dict
keys were strings, and strings also accept destructuring bind!
>>> x, y, z, u, v = "teste"
>>> print(x, y, z)
t e s
>>> print(u, v)
t e
Like Name
has 4 letters, but the tuple (last, first)
Python had nowhere to put the last two letters. Interestingly, if your keys had 2 letters, the error message would be different:
>>> person = {"FN": "Barack", "SN": "Obama"}
>>> for last, first in person:
... print(person[last, first])
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
KeyError: ('F', 'N')
In which case he would be assigning the last
the value "F"
and the first
the value "N"
. And of course, since the keys of dictionaries are strings and not tuples, the key ("F", "N")
was not found in the dictionary...