What does this "people[last, first]" mean in Python?

Asked

Viewed 126 times

2

It’s the first time I’ve seen this syntax people[last, first] with the comma separating the Dexes in Python. I don’t even know what data structure is people.

The question is

What does this statement do:

for last, first in people:
    print(last, first, people[last, first])

Be sure you understand the Structure of the Dictionary and its Keys.

From this last advice it seems that people is the dictionary, but I think with a normal dictionary this syntax is not allowed, because this code:

 person = {"Name": "Barack", "Surname": "Obama"}

 for last, first in person:
   print(person[last, first])

make me mistake:

Valueerror: Too Many values to unpack (expected 2)

People have to have 2 values, because these are saved in last and first...

1 answer

1


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

Browser other questions tagged

You are not signed in. Login or sign up in order to post.