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

2

This is the first time I see this people[last, first] syntax with the comma separating the indexes in Python. I do not 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 are 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])

Give me an error:

  

ValueError: Too many values to unpack (expected 2)

People have to have 2 values, as they are saved in last and first ...

    
asked by anonymous 22.11.2014 / 22:59

1 answer

2

Probably people is a dictionary that maps tuples to 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 is just like a list, only immutable:

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, people[last, first] is the same as people[(last, first)] .

As for the data type people , I figured it was a dict because it's the only way this code makes sense. Arrays only allow indexing by number, not by tuples, so people is not an array. Since a dict allows tuples as keys, and as for applied to a dictionary iterates over its keys, I imagined this to be 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 both enumerate and items return tuples. In this way, you can do a destructuring assignment (or destructuring bind ) of your 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 came to your "strange" error message: "too many values to unpack" means that you attempted a destructuring bing where there were more right than 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 this happen? Simple, in their dict the 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

Since Name has 4 letters, but the tuple (last, first) only has 2 elements, Python has nowhere to put the last two letters. Curiously, 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 this case it would be assigning the last the value "F" and the first the value "N" . And of course, since the dictionary keys are strings and not tuples, the ("F", "N") key was not found in the dictionary ...

    
23.11.2014 / 02:17