Porter Robinson Porter Robinson - 6 months ago 8
Python Question

How do I work with a nested dictionary's name?

I'm writing a program using dictionaries nested within a list. I want to print the name of each dictionary when looping through the list, but don't know how to do that without calling the entire contents of the dictionary. Here is my code:

sam = {
'food' : 'tortas',
'country' : 'mexico',
'song' : 'Dream On',
}
dave = {
'food' : 'spaghetti',
'country' : 'USA',
'song' : 'Sweet Home Alabama',
}

people = [sam, dave]

for person in people:
for key, value in sorted(person.items()):
print( #person's name +
"'s favorite " + key + " is " + value + ".")


Here is the output:

's favorite country is mexico.

's favorite food is tortas.

's favorite song is Dream On.

's favorite country is USA.

's favorite food is spaghetti.

's favorite song is Sweet Home Alabama.


Everything works, I just need the names of my dictionaries to print. What's the solution?

EDIT:
Thanks for the great input. This program is for a practice example in "Python Crash Course" by Eric Matthes, so the inefficient "dictionaries inside list" format is intentional. That said, I got a lot out of your comments, and altered my code to get the desired output:

sam = {
#Added a 'name' key-value pair.
'name' : 'sam',
'food' : 'tortas',
'country' : 'mexico',
'song' : 'Dream On',
}
dave = {
'name' : 'dave',
'food' : 'spaghetti',
'country' : 'USA',
'song' : 'Sweet Home Alabama',
}

people = [sam, dave]

for person in people:
for key, value in sorted(person.items()):
#Added if statement to prevent printing the name.
if key != 'name':
print(person['name'].title() + "'s favorite " + key + " is " + value + ".")
#Added a blank line at the end of each for loop.
print('\n')


Here is the output:

Sam's favorite country is mexico.
Sam's favorite food is tortas.
Sam's favorite song is Dream On.


Dave's favorite country is USA.
Dave's favorite food is spaghetti.
Dave's favorite song is Sweet Home Alabama.


Thanks again, all who provided insightful answers.

Answer

Values in a list aren't really variables any more. They aren't referred to by a name in some namespace, but by an integer indicating their offsets from the front of the list (0, 1, ...).

If you want to associate each dict of data with some name, you have to do it explicitly. There are two general options, depending on what's responsible for tracking the name: the collection of people, or each person in the collection.

The first and easiest is the collections.OrderedDict --- unlike the normal dict, it will preserve the order of the people in your list.

from collections import OrderedDict

sam = {
  'food': 'tortas',
  'country': 'Mexico',
  'song': 'Dream On',
  }
dave = {
  'food': 'spaghetti',
  'country': 'USA',
  'song': 'Sweet Home Alabama',
  }
# The OrderedDict stores each person's name.
people = OrderedDict([('Sam', sam), ('Dave', dave)])

for name, data in people.items():
    # Name is a key in the OrderedDict.
    print('Name: ' + name)
    for key, value in sorted(data.items()):
        print('  {0}: {1}'.format(key.title(), value))

Alternatively, you can store each person's name in his or her own dict... assuming you're allowed to change the contents of those dictionaries. (Also, you wouldn't want to add anything to the data dictionary that would require you to change / update the data more than you already do. Since most people change their favorite food or song much more often than they change their name, this is probably safe.)

sam = {
# Each dict has a new key: 'name'.
  'name': 'Sam',
  'food': 'tortas',
  'country': 'Mexico',
  'song': 'Dream On',
  }
dave = {
  'name': 'Dave',
  'food': 'spaghetti',
  'country': 'USA',
  'song': 'Sweet Home Alabama',
  }
people = [sam, dave]

for data in people:
    # Name is a value in the dict.
    print('Name: ' + data['name'])
    for key, value in sorted(data.items()):
        # Have to avoid printing the name again.
        if 'name' != key:
            print('  {0}: {1}'.format(key.title(), value))

Note that how you print the data depends on whether you store the name in the collection (OrderedDict variant), or in each person's dict (list variant).