Nico
Nico

Reputation: 194

Adding a dictionary item that is a dictionary itself

Consider following dictionary:

dict1 = {"A":{"B":"C"}}
print(dict1["A"]["B"])

This prints 'C'

I can now modify my dictionary like this

dict1["A"]["B"] = "D"
dict1["A"]["E"] = "F"
dict1["B"] = "G"
print(dict1)

And the output is

{'A': {'B': 'D', 'E': 'F'}, 'B': 'G'}

but I can't do this:

dict1["C"]["H"] = ["I"]

this however works:

dict2 = {"H":"I"}
dict1["C"] = dict2
print(dict1)

Output:

{'A': {'B': 'D', 'E': 'F'}, 'B': 'G', 'C': {'H': 'I'}}

Is there an alternative that doesn't require creating an additional dictionary?

I am just playing around to learn the language and not working on a concrete project. Still, any help would be appreciated

Upvotes: 3

Views: 76

Answers (5)

BoppreH
BoppreH

Reputation: 10173

There's a one-liner tree in https://gist.github.com/hrldcpr/2012250. It was posted as a cute hack, but works reasonably well.

from collections import defaultdict
def tree(): return defaultdict(tree)

users = tree()
users['harold']['username'] = 'hrldcpr'
users['handler']['username'] = 'matthandlersux'

Because of the defaultdict, each access on an undefined key generates a new value, and because of the recursion the new value will also be a new tree.

Upvotes: 0

noɥʇʎԀʎzɐɹƆ
noɥʇʎԀʎzɐɹƆ

Reputation: 10647

You haven't created the dictionary C yet. In python you must first create it before editing it. Like this:

dict1 = {}
dict1["C"] = {} # First create it before modifying it
dict1["C"]["H"] = ["I"]
print(dict1)

Let me explain.

foomain["C"] = 'blah'

sets it, but

foomain['C']['H'] = 'blah'

attempts to find foomain['C'], and fails. If it worked, it would then take that dictionary and use the assignment operator on it to assign blah to ['C']['H'].

It's like saying:

Okay, go find `foomain['C']`, then assign 'blah' to key 'H'

Instead of:

Okay, assign 'blah' to `foomain['C']['H']`

In other words, assignment and getting are entirely different in python.

Upvotes: 2

user447688
user447688

Reputation:

dict1["C"]["H"] = ["I"]

In the above, the problem is that dict1["C"] has not been initialized, and so it is not known whether it is a dict and can be assigned a sub-element like ["H"] (or whether it is just, say, an integer and assigning to ["H"] would be an error).

There are packages to enable what you're talking about, and using a defaultdict would work for a single level of nestedness. But especially if you are starting out, it's probably better that you deal with such things explicitly.

val = dict1.get("C")
if isinstance(val, dict)
    dict1["C"]["H"] = "I"
else
    dict["C"] = {"H": "I"}

Upvotes: 1

hspandher
hspandher

Reputation: 16733

You can use setdefault which would assign default value in case of key error.

dict1.setdefault('C', {})['H'] = 'I'

Or you can altogether use defaultdict instead of dict.

from collections import defaultdict

Upvotes: 0

MK.
MK.

Reputation: 34527

Why would dict1["C"]["H"] = ["I"] work if there is no element "C" in dict1? Do this:

dict1["C"] = {}
dict1["C"]["H"] = ["I"]

Upvotes: 3

Related Questions