2010-06-26 9 views
11

Google et les documents en ligne ne fournissent pas beaucoup d'informations sur ma requête, alors j'ai pensé que je demanderais à la communauté ici.Dans une dictée de dicts, comment émulez-vous le comportement d'auto-vivification de Perl?

En Perl, vous pouvez facilement configurer un hachage-of-a-hachage-of-a-hachage et de tester la clé finale comme ceci:

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

Quel est l'équivalent 'meilleures pratiques' en Python ?

Répondre

14

Le plus proche équivalent est probablement quelque chose comme ce qui suit:

import collections 

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

hash = hasher() 
hash['element1']['sub1']['subsub1'] = 'value1' 
if 'subsub1' in hash['element1']['sub1']: 
    print 'found value' 
+3

Notez que 'si sub1 dans hash ['phony']' crée une clé '' bidon ''. Cela peut être problématique, d'autant plus que l'OP veut tester si les clés existent ... – unutbu

+0

@ ~ unutbu: l'OP demande: "test the * final * key", donc 'hash ['element1'] ['sub1'] = dict (subsub1 = 'value1') 'fera l'affaire. – jfs

+0

Merci, c'est très utile. – jbb

5

Quant à savoir si cela est une bonne pratique en Python est à débattre:

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

Mais, il fonctionne certainement et est très élégant, si cela fonctionne pour vous.

L'inconvénient majeur est que vous n'avez pas d'accès intermédiaire. Vous ne pouvez pas faire:

if ('element1', 'sub1') in hash: 
    print "found value" 
+1

Vous devriez expliquer ce qui se passe. C'est un hash/dict unique avec un [tuple] à 3 éléments (http://docs.python.org/library/functions.html#tuple) comme clé. Vraiment pas la même chose, bien que vous l'ayez quelque peu indiqué avec votre deuxième exemple. –

+0

Une manière intéressante de gérer l '"inconvénient" (si vous le considérez comme tel) dans la réponse d'Alex Martelli, souligné par ~ unutbu. –

+0

En effet, ce n'était pas ce que je cherchais - mais néanmoins intéressant. Merci pour le conseil. – jbb

0

Je ne sais pas si je vais tout accord, mais comment je déclare généralement des dictionnaires de dictionnaires:

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

En ce qui concerne la vérification des la présence d'un élément, je suis d'accord avec cette approche:

try: 
    someObj['element1']['sub1']['subsub1'] 
except KeyError: 
    print('no value found') 
else: 
    print('found value') 
3
from collections import defaultdict 

tree = lambda: defaultdict(tree) 

t = tree() 

t[1][2][3] = 4 
t[1][3][3] = 5 
t[1][2]['test'] = 6 

de wikipedia Autovivification

+1

En plus d'utiliser 'lambda', en quoi est-ce différent de la réponse acceptée il y a 3 ans? – MattH