I'm leaving my original solution for posterity:
CONTEXT = {
"database": {
"port": 9990,
"users": ["number2", "dr_evil"]},
"admins": ["[email protected]", "[email protected]"],
"domain": {"name": "virtucon.com"}}
def getitem(context, *keys):
node = context
for key in keys:
node = node[key]
return node
if __name__ == "__main__":
print getitem(CONTEXT, "database")
print getitem(CONTEXT, "database", "port")
print getitem(CONTEXT, "database", "users", 0)
print getitem(CONTEXT, "admins")
print getitem(CONTEXT, "domain", "name")
try:
getitem(CONTEXT, "database", "nosuchkey")
except KeyError, e:
print "Error:", e
But here's a version that implements an approach similar to the getitem interface suggested by doublep. I am specifically not handling dotted keys, but rather forcing the keys into separate nested structures because that seems cleaner to me:
CONTEXT = {
"database": {
"port": 9990,
"users": ["number2", "dr_evil"]},
"admins": ["[email protected]", "[email protected]"],
"domain": {"name": "virtucon.com"}}
if __name__ == "__main__":
print CONTEXT["database"]
print CONTEXT["database"]["port"]
print CONTEXT["database"]["users"][0]
print CONTEXT["admins"]
print CONTEXT["domain"]["name"]
try:
CONTEXT["database"]["nosuchkey"]
except KeyError, e:
print "Error:", e
You might notice that what I've really done here is eliminate all ceremony regarding accessing the data structure. The output of this script is the same as the original except that it does not contain a dotted key. This seems like a more natural approach to me but if you really wanted to be able to handle dotted keys, you could do something like this I suppose:
CONTEXT = {
"database": {
"port": 9990,
"users": ["number2", "dr_evil"]},
"admins": ["[email protected]", "[email protected]"],
"domain": {"name": "virtucon.com"}}
def getitem(context, dotted_key):
keys = dotted_key.split(".")
value = context
for key in keys:
try:
value = value[key]
except TypeError:
value = value[int(key)]
return value
if __name__ == "__main__":
print getitem(CONTEXT, "database")
print getitem(CONTEXT, "database.port")
print getitem(CONTEXT, "database.users.0")
print getitem(CONTEXT, "admins")
print getitem(CONTEXT, "domain.name")
try:
CONTEXT["database.nosuchkey"]
except KeyError, e:
print "Error:", e
I'm not sure what the advantage of this type of approach would be though.