Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

Python Python Collections (Retired) Dictionaries Unpacking Dictionaries

David Savoir
David Savoir
6,172 Points

'list' object has no attribute 'items'

dicts = [
    {'name': 'Michelangelo',
     'food': 'PIZZA'},
    {'name': 'Garfield',
     'food': 'lasanga'},
    {'name': 'Walter',
     'food': 'pancakes'},
    {'name': 'Galactus',
     'food': 'worlds'}
]

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

def string_factory(dictionaryfactory, stringfactory):
    for k,v in dictionaryfactory.items():
        return (string.format(**dictionaryfactory))

string_factory(dicts, string)

Keep getting this error for the code above. Can´t seem to fix it. Any help would be appreciated.

11 Answers

I'll give you a hint at how I solved it ...

dicts = [
    {'name': 'Michelangelo',
     'food': 'PIZZA'},
    {'name': 'Garfield',
     'food': 'lasanga'},
    {'name': 'Walter',
     'food': 'pancakes'},
    {'name': 'Galactus',
     'food': 'worlds'}
]

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

def string_factory(dicts, string):
  strings = []
  # for loop through dicts
    # append to the strings variable using string.format(**dict))
  return strings

print(string_factory(dicts, string))

@Ryan Carson Awesome help. Thanks.

Could you post the final answer? I'm still not getting it.

Parsenz Dev
Parsenz Dev
13,198 Points

"dicts" in your code is a list, but your "string_factory" function attempts to use a python dictionary method (items()) on it. I assume you want to get each dict from the list first, then get the key and value, so...

def string_factory(dictionaryFactory, stringfactory):
    for item in dictionaryFactory:
        for k,v in item.items():
            return ...
David Savoir
David Savoir
6,172 Points

Thanks clearing that up. The method I am supposed to use applies to dictionaries, yet after adding my return line described above, I get :

format() argument after ** must be a mapping, not list

When I run this code through Python Tutor, I does recognize "dicts" as a dictionary:

http://tinyurl.com/mtuvmrp

Any ideas ? Thx in advance.

Parsenz Dev
Parsenz Dev
13,198 Points

Ahh...I see what you're going for now. I was trying to keep your code as close as possible to what you had.

Because dicts above is a list, you want to go through that list and get each item contained within

def string_factory(dict_factory):
    """
    To confirm dict_factory is a list...
    """
    print type(dict_factory)
    return_str = ''

    for item in dict_factory:
        """
        At this point, we have an item from the list. 
        This item is a dict. We can print it to be sure.
        """
        print type(item)

        # We can return this using string interpolation which is exactly what you are attempting above
        return_str += 'Hi, I\'m %s and I like to eat %s. \n' % (item['name'], item['food'])
    return return_str

I hope this clears things up!

David Savoir
David Savoir
6,172 Points

Thanks for the help. The assignment requires me to do the following though:

Create a function named string_factory that accepts a list of dictionaries boldand bolda string. Return a list of strings made by filling values from the dictionaries into the string.

Since - as it turns out - this is a list, I tried using * in stead of **, still no success.

I looked into unpacking lists. Somehow I feel like this could be a good solution: https://docs.python.org/2/tutorial/controlflow.html#unpacking-argument-lists

Only problem is: I have no idea how to apply it to this scenario :-(

Parsenz Dev
Parsenz Dev
13,198 Points
dicts = [
        {'name': 'Michelangelo', 'food': 'PIZZA'},
        {'name': 'Garfield', 'food': 'lasanga'},
        {'name': 'Walter', 'food': 'pancakes'},
        {'name': 'Galactus', 'food': 'worlds'}
    ]

    def string_factory(dict_factory, string_format):
        # Create our empty list
        return_list = []

        for item in dict_factory:
            # So we can go ahead and append this to our return_list
            return_list.append(string_format % (item['name'], item['food']))

        return return_list

    string_format_base = 'Hi, I\'m %s and I like to eat %s.'

    # Call the function
    string_factory(dicts, string_format_base)
David Savoir
David Savoir
6,172 Points

Thanks ! This works fine in the command line, but in the treehouse environment I get the error:

(TypeError)not all arguments converted during string formatting.

I looked this up and this seems to be an error during formatting with %s

So changed:

```
return_list.append(string_format % (item['name'], item['food']))
string_format_base = 'Hi, I\'m %s and I like to eat %s.'
```

To:

```
return_list.append(string_format.format(item['name'], item['food']))
string_format_base= "Hi, I'm {0} and I like to eat {1}."
```

Those changes work fine in command line (python 3.3), but in the treehouse environment I get the following error message:

Bummer! 'name'

What gives ?

Kenneth Love
Kenneth Love
Treehouse Guest Teacher

Since string has named placeholders, you have to give named arguments to str.format(). So string.format(name=item['name'], food=item['food']) will do what you're expecting (notice the named arguments). OR you can do string.format(**item) and it'll do the same thing.

David Savoir
David Savoir
6,172 Points

Figured it out. Thanks guys !

Tony Brackins
Tony Brackins
28,236 Points

Hey Ryan Carson are you able to give what your final answer was? I"m stuck and none of this is helping.

Hi Tony, hey I assume you no longer need answer to this, right? Seem like it was posted like 2 months ago but I just made it work after Carson's tip. Will be happy to share it too, just that I'm not sure if will it be of use for you.

Ricardo Rodriguez I'd appreciate it if you posted the answer. Thanks!

Joe Law
Joe Law
5,040 Points

Hey people, can you clarify for me? what does it means by the output should be a list?

This is my code:

def string_factory(dicts, string):
  combined_dict = {}
  new_string = ""
  for dictc in dicts:
    combined_dict.update(dictc)
  new_string = string.format(**combined_dict)
  return new_string

string_factory(dicts, string)
Kenneth Love
Kenneth Love
Treehouse Guest Teacher

It should return a list, not a string. It'll be a list of strings, though.

Joe Law
Joe Law
5,040 Points

Thanks Kenneth, solved it yesterday night, should have removed the question earlier. Btw, really thank you, your classes are fun!

I'm also getting the same error. Can you elaborate on how to fix the problem cause I'm stuck.

Kenneth Love
Kenneth Love
Treehouse Guest Teacher

Carina De Jager In Joe's code above, he's returning a string at the end. The function should return a list of strings.

What I'm not understanding is how to change it I guess.

Joe Law
Joe Law
5,040 Points

When the new_string is returned, only : "Hi, I'm Galactus and I love to eat worlds!" is returned.

While the challenge is expecting this : ["Hi, I'm Michelangelo and I love to eat PIZZA!", "Hi, I'm Garfield and I love to eat lasanga!", "Hi, I'm Walter and I love to eat pancakes!", "Hi, I'm Galactus and I love to eat worlds!"]

There for you need to add something to the function to create a list like this. :D.

**Hints : .append Hope this helps. :D :D

Thank u!

Joe Law
Joe Law
5,040 Points

You're welcomed. Work harder~ you'd stopped for 2 days. All the best! I am learning here too. hehehhe.

Lol. I hadn't stopped for two days. Just didn't have a sec to pop in and say thanks after I fixed it until now. Finding this entire section quite confusing... :-o

Joe Law
Joe Law
5,040 Points

I see, all the best! but no worries, as you continue, you will get better and better, try to google up more and read up, you will improve.