views:

162

answers:

4

Both Google and the online docs are not delivering much insight on my query, so I thought I would ask the community here.

In Perl, you can easily setup a hash-of-a-hash-of-a-hash and test the final key like so:

my $hash = {};
$hash{"element1"}{"sub1"}{"subsub1"} = "value1";
if (exists($hash{"element1"}{"sub1"}{"subsub1"})) {
   print "found value\n";
}

What's the 'best-practice' equivalent in Python?

+8  A: 

The closest equivalent is probably something like the following:

import collections

def hasher():
  return collections.defaultdict(hasher)

hash = hasher()
hash['element1']['sub1']['subsub1'] = 'value1'
if 'subsub1' in hash['element1']['sub1']:
  print 'found value'
Alex Martelli
Note that `if sub1 in hash['phony']` creates a key `'phony'`. This might be problematic, especially since the OP wants to test if keys exist...
unutbu
@~unutbu: the OP asks: "test the *final* key", therefore `hash['element1']['sub1'] = dict(subsub1='value1')` will do.
J.F. Sebastian
Thanks, this is quite helpful.
jbb
+2  A: 
adict={'element1':{'sub1':{'subsub1':'value1'}}}

If you want to test that all the keys exist, you could use try...except KeyError:

try:
    adict['element1']['sub1']['subsub1']
except KeyError:
    print('no dice')
else:
    print('found value')
# found value

try:
    adict['phony']['baloney']
except KeyError:
    print('no dice')
else:
    print('found value')
# no dice

If you only want to test the existence of the final key:

if 'subsub1' in adict['element1']['sub1']:
    print('found value')
unutbu
+3  A: 

As to whether this is a best practice in Python is up to debate:

hash = {}
hash['element1', 'sub1', 'subsub1'] = 'value'
if ('element1', 'sub1', 'subsub1') in hash:
    print "found value"

But, it certainly works and is very elegant, if it works for you.

The major drawback is that you don't have intermediate access. You can't do:

if ('element1', 'sub1') in hash:
   print "found value"
carl
You should explain what's happening. This is a single hash/dict with a 3-element [tuple](http://docs.python.org/library/functions.html#tuple) as a key. Really not the same thing, though you did somewhat indicate that with your second example.
Matthew Flaschen
Interesting way to handle the "drawback" (if you consider it to be such) in Alex Martelli's answer, pointed out by ~unutbu.
David Zaslavsky
Indeed, this wasn't what I was looking for - but interesting nonetheless. Thanks for the tip.
jbb
A: 

I don't know if I'll get any agreement, but this is how I typically declare dictionaries of dictionaries:

someObj = {
  'element1': {
    'sub1': {
      'subsub1': 'value1'
    }
  }
}

As for checking for the presence of an element, I agree with this approach:

try:
  someObj['element1']['sub1']['subsub1']
except KeyError:
  print('no value found')
else:
  print('found value')
g.d.d.c