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

Packing and Unpacking

Code Challenge problem:

Let's test unpacking dictionaries in keyword arguments. You've used the string .format() method before to fill in blank placeholders. If you give the placeholder a name, though, like in template below, you fill it in through keyword arguments to .format(), like this: template.format(name="Kenneth", food="tacos") Write a function named string_factory that accepts a list of dictionaries as an argument. Return a new list of strings made by using ** for each dictionary in the list and the template string provided.

Error message was: positional argument follow keyword argument (string_factory.py, line 12)

With my understanding, to unpack, I will use the double asterisks to introduce the values I want to unpack inside the call function.

Please if you are helping out with this, I will appreciate some explanation on what I did wrong and what I should have done instead. In that way I will learn better and understand your own solution to the problem.

My code is attached.

Thank you so much for your help.

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 string_factory(template = "Hi, I'm {name} and I love to eat {food}!"):
    if template:
        return (template.format(name = "name", food = "food"))

string_factory(**{"name": "Michelangelo", "food": "PIZZA"}, {"name": "Garfield", "food": "lasagna"})

5 Answers

Steven Parker
Steven Parker
230,995 Points

Here's a few hints:

  • don't modify the provided code, "template" is defined as a global you can use in the function
  • your function "accepts a list of dictionaries as an argument", give this a name other than "template"
  • you will need a loop to handle multiple items in the argument list
  • you will use "format" in the loop with "template" to build up a list of strings to return
  • the format call will provide an opportunity to use unpacking to create named arguments
  • only after the loop is finished, you will return the newly-created list of strings

Following your hints, I tried this but I'm not yet there.

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

string_factory(**{"name": "Michelangelo", "food": "PIZZA"}, {"name": "Garfield", "food": "lasagna"})
Steven Parker
Steven Parker
230,995 Points

OK, here's another round of hints:

  • don't modify the provided code, leave "template" defined as a global outside of the function
  • use a single variable to represent each item in the loop (like "for item in value:")
  • when you format using the template, be sure to add the result to a new list
  • the format call will provide an opportunity to use unpacking on your dictionary item
  • only after the loop is finished, you will return the newly-created list of strings (not the original argument)
  • you only need to define the function, you will not need to call it yourself

@Steven Parker

I think i'm lost. It's still not panning out.

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

def string_factory(steak):
    values = [{"name": "Michelangelo", "food": "PIZZA"}, {"name": "Garfield", "food": "lasagna"}]
    new = []
    for item in values:
        good = [(template.format(name = "name", food = "food"))]
        new += good
    return new
Steven Parker
Steven Parker
230,995 Points

You're pretty close, but:

  • the dictionary list comes in as the argument, you do not want any literals
  • the literal values in the comments are just sample models, they will not be used
  • the format argument doesn't need explicit names if the unpacking operator is used

@Steven Parker

Still finding the exit. If I understand what you are saying, the dictionary will be used with double asterisk to call function while unpacking and the unpacking will not come inside of the function. I tried with the lines below but no success.

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

def string_factory(list):
    new = []
    for item in list:
        good = [(template.format(name, food))]
        new += good
    return (new)
Steven Parker
Steven Parker
230,995 Points

You're almost there. Here's what I was hinting about regarding the unpacking operator:

        good = [ template.format(**item) ]

@Steven Parker

Sigh of relief at last! Thanks a million for helping out with those hints. And I do appreciate your patience.

You can also save yourself a line of code with not using the "good" variable. Just add the combined template directly into the new list.

new += [template.format(**item)]