Defining Multiple Dictionaries Within a Loop in Python

22,693

Solution 1

I think instead of creating a variable for each name you can create a dict of names with each name pointing to a dictionary.

>>> names=["lloyd", "alice", "tyler"]
>>> keys=["homework", "quizzes", "tests"]
>>> dic={ name.capitalize():{ key:[] for key in keys} for name in names}
>>> dic
{'Tyler': {'quizzes': [], 'tests': [], 'homework': []}, 
 'Lloyd': {'quizzes': [], 'tests': [], 'homework': []},
 'Alice': {'quizzes': [], 'tests': [], 'homework': []}}

Now to access Tyler simply use:

>>> dic['Tyler']
{'quizzes': [], 'tests': [], 'homework': []}

Solution 2

In python you cannot create local variables at runtime. You have to explicitly assign a value to them.

Something like this:

locals()['lloyd'] = {...}
locals()['alice'] = {...}
locals()['tyler'] = {...}

does not create the local variables lloyd, alice and tyler:

>>> def some_function():
...     locals()['lloyd'] = {}
...     print lloyd
... 
>>> some_function()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in some_function
NameError: global name 'lloyd' is not defined

Quoting from the documentation for locals():

Note The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the interpreter.

What you can do is to create global variables at runtime, using the dictionary returned by globals(). Although I don't see why you should do something like that.

However you could use the copy module to avoid repeating the dict definition:

import copy
base_dict = {"homework": [], "quizzes": [], "tests": []}
lloyd = copy.deepcopy(base_dict)
alice = copy.deepcopy(base_dict)
tyler = copy.deepcopy(base_dict)
for the_dict, name in ((lloyd, "lloyd"), (alice, "alice"), (tyler, "tyler")):
    the_dict["name"] = name.capitalize()

Or without the loop:

import copy
base_dict = {"homework": [], "quizzes": [], "tests": []}
lloyd = copy.deepcopy(base_dict)
alice = copy.deepcopy(base_dict)
tyler = copy.deepcopy(base_dict)
lloyd["name"], alice["name"], tyler["name"] = "lloyd", "alice", "tyler"

Depending on what you want to do using a defaultdict could be a good idea:

from collections import defaultdict
lloyd = defaultdict(list)
alice = defaultdict(list)
tyler = defaultdict(list)
lloyd["name"], alice["name"], tyler["name"] = "lloyd", "alice", "tyler"

The defaultdict, instead of raises a KeyError when the key is not found, it creates a default value(in this case an empty list) and sets that value as the value of the key, hence you don't need to specify "tests": [].

Share:
22,693
Admin
Author by

Admin

Updated on July 09, 2022

Comments

  • Admin
    Admin almost 2 years

    What I'm looking to do is to define three very similar dictionaries with only subtle differences. If you recognize this it is one of the problems from the Codeacademy course on Python, and I'm looking to do it a little more elegantly. Anyways, here's what I have:

    import string
    for name in ["lloyd", "alice", "tyler"]:
        name = {"name": string.capitalize(name), "homework": [], "quizzes": [], "tests": []}
    

    This isn't working. What I want is three dictionaries, which have the names "lloyd" "alice" and "tyler" and with keys of their names (but capitalized), "homework", "quizzes", and "tests"

    To clarify, the output I want is equivalent to this:

    lloyd = {"name": "Lloyd", "homework": [], "quizzes": [], "tests": []}
    alice = {"name": "Alice", "homework": [], "quizzes": [], "tests": []}
    tyler = {"name": "Tyler", "homework": [], "quizzes": [], "tests": []}
    
  • Ashwini Chaudhary
    Ashwini Chaudhary about 11 years
    there's no need of importing string, you can simply use name.capitalize().