Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python Python Collections (2016, retired 2019) Dictionaries String Formatting with Dictionaries

Unpacking Dictionaries Python

values = [{"name": "Michelangelo", "food": "PIZZA"}, {"name": "Garfield", "food": "lasagna"}]template = "Hi, I'm {name} and I love to eat {food}!"

def string_factory(values):
    new_list = []
    for each_dict in values:
        new_list.append(template.format(**each_dict))
    return new_list

I was really confused with this exercise because it was shown differently in the video.
What trip me up was why did Keeneth use 2 parameters in the unpacker function?
In this exercise with the name and food, these 2 parameters were not used. Also right after the format, Keneeth again used 2 parameters in order to feed it into the sentence. While in the name and food was not used to feed it into the template.format?

Also, in the food exercise, each dictionary was unpacked within the sentence vs in Keneeth's version he unpacked it with the 2 stars when he called up the unpacker function. So where should we use the 2 stars to unpack dictionaries?
When you call up the function or the parameters of the function?

def unpacker(first_name=None, last_name=None):
    if first_name and last_name:
        print("Hi {} {}".format(first_name, last_name)
    else:
        print("hi no name!")

unpacker(**{"last_name": "Love", "first_name": "Kenneth"})
string_factory.py
# Example:
# values = [{"name": "Michelangelo", "food": "PIZZA"}, {"name": "Garfield", "food": "lasagna"}]
# string_factory(values)
# ["Hi, I'm Michelangelo and I love to eat PIZZA!", "Hi, I'm Garfield and I love to eat lasagna!"]

template = "Hi, I'm {name} and I love to eat {food}!"




def unpacker(first_name=None, last_name=None):
    if first_name and last_name:
        print("Hi {} {}".format(first_name, last_name)
    else:
        print("hi no name!")

unpacker(**{"last_name": "Love", "first_name": "Kenneth"})
austin bakker
austin bakker
7,105 Points

I am stuck on the same question, i can't seem to find out how to code it, and what is requested of me to code. I also keep on getting the error "couldn't import string_factory." <p>

Example:

values = [{"name": "austin", "food": "PIZZA"}, {"name": "Garfield", "food": "lasagna"}]

string_factory(values)

["Hi, I'm Michelangelo and I love to eat PIZZA!", "Hi, I'm Garfield and I love to eat lasagna!"]

def string_factory(values): template = "Hi, I'm {} and I love to eat {}!".format(name,food) return template

</p>

3 Answers

Ryan Cross
Ryan Cross
5,742 Points

I agree with the first two. The third case I'm not sure. In that code snippet format....which is a function, a built-in...** and some dicts is unpacking as in 1.before an argument when calling up a function.

This is for Austin....

#This is the profile database, it consist of 2 dictionaries
profile = [{"name": "Michelangelo", "food": "PIZZA"}, {"name": "Garfield", "food": "lasagna"}]

#This is the script sentence, you take the name & the food from the dictionaries above, and put it in this sentence
template = "Hi, I'm {name} and I love to eat {food}!"

#This function will be in charge of extracting the name & food from profile dictionaries
def string_factory(values):

 #This new list will contain the newly made sentences, after you extract the name and food and put plug it into template sentence
  new_list = []

 #Since in the profile dictionary, there are actually 2 dictionaries, so you have to loop through them   to extract the information for one dictionary at a time
  for each_dict in values:
    new_list.append(template.format(**each_dict))

  #instead of returning the new_list like the exercise ask you, I'm printing the new_list dictionary to demonstrate the result of the function

for line in (new_list):
    print(line)

string_factory(profile)

#********************************************************
#This is the product of the string_factory function
#Hi, I'm Michelangelo and I love to eat PIZZA!
#Hi, I'm Garfield and I love to eat lasagna!

#See how using the template sentence, you put in the name and what food the person likes to eat.  
Ryan Cross
Ryan Cross
5,742 Points

"So where should we use the 2 stars to unpack dictionaries? When you call up the function or the parameters of the function?"

I hope this helps. I also had a bear of a time with this. As you go through the course be sure to have another way to get over a hump. I have a book and some good youtube channels. For when you don't get it from the lesson.

The input to the function at the moment it is called is the ARGUMENT. foo(args_here) The input to the function as it is defined is the PARAMETER. def foo(parms_here):

** in the arguments will unpack a dictionary. The function is called with a dictionary argument.What the function is passed are a bunch of keyword pairs.

**kwargs in the parameters will catch any and all incoming keyword pairs and hold them in a dictionary. You deal with them in your function definition using code along the lines of: def foo(**kwargs): for item in kwargs.items(): print(item) You still have all your keyword pairs there but they're in a dictionary (kwargs) and you deal with them as such.

There's also the whole *args thing he didn't mention. Works same but for non keyword items. Unpacking in arguments packing in parameters. *args will unpack a tuple into singles, unpack a string into chars, a list into items etc. *args in the parms will catch any number of (non keyword) args and stash them in a tuple.

Hi Ryan, So there seems to be 3 places where ** can go.

  1. before an argument when calling up a function
  2. before parameters inside when defining a function
  3. inside a function as an example here when you loop it inside the string_factory function

What I'm still confused on

  1. why don't you unpack and put ** right before the parameters in the string_factory function, instead its later on in the loop ex. from string_factory function
    for each_dict in values: new_list.append(template.format(**each_dict))

  2. since values is a dictionary, which contains name (keywords and values) how does it know which is a keyword and which is a value?

  3. In Keneeth's example of unpacker function def unpacker(first_name=None, last_name=None) you see how he specificed first_name & last_name? print("Hi {} {}".format(first_name, last_name) Why don't we do that with string_factory function?

values = [{"name": "Michelangelo", "food": "PIZZA"}, {"name": "Garfield", "food": "lasagna"}]template = "Hi, I'm {name} and I love to eat {food}!"

def string_factory(values):
    new_list = []
    for each_dict in values:
        new_list.append(template.format(**each_dict))
    return new_list