79 votes

Quel est le meilleur moyen d'initialiser un dict of dicts en Python?

Beaucoup de fois en Perl, je vais faire quelque chose comme ça:

 $myhash{foo}{bar}{baz} = 1
 

Comment pourrais-je traduire cela en Python? Jusqu'ici j'ai:

 if not 'foo' in myhash:
    myhash['foo'] = {}
if not 'bar' in myhash['foo']:
    myhash['foo']['bar'] = {}
myhash['foo']['bar']['baz'] = 1
 

Y a-t-il un meilleur moyen?

106voto

John Fouhy Points 14700

Si la quantité de nidification dont vous avez besoin est fixe, collections.defaultdict est merveilleux.

par exemple nidification deux profonds:

 myhash = collections.defaultdict(dict)
myhash[1][2] = 3
myhash[1][3] = 13
myhash[2][4] = 9
 

Si vous voulez passer à un autre niveau d'imbrication, vous devrez faire quelque chose comme:

 myhash = collections.defaultdict(lambda : collections.defaultdict(dict))
myhash[1][2][3] = 4
myhash[1][3][3] = 5
myhash[1][2]['test'] = 6
 

edit: MizardX souligne que nous pouvons obtenir toute la généricité avec une simple fonction:

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

Maintenant nous pouvons faire:

 myhash = makehash()
myhash[1][2] = 4
myhash[1][3] = 8
myhash[2][5][8] = 17
# etc
 

97voto

nosklo Points 75862
 class AutoVivification(dict):
    """Implementation of perl's autovivification feature."""
    def __getitem__(self, item):
        try:
            return dict.__getitem__(self, item)
        except KeyError:
            value = self[item] = type(self)()
            return value
 

Essai:

 a = AutoVivification()

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

print a
 

Sortie:

 {1: {2: {'test': 6, 3: 4}, 3: {3: 5}}}
 

13voto

zweiterlinde Points 5984

Y a-t-il une raison pour laquelle il faut que ce soit une dictée? S'il n'y a aucune raison impérieuse pour cette structure particulière, vous pouvez simplement indexer le dict avec un tuple:

 mydict = {('foo', 'bar', 'baz'):1} # Initializes dict with a key/value pair
mydict[('foo', 'bar', 'baz')]      # Returns 1

mydict[('foo', 'unbar')] = 2       # Sets a value for a new key
 

Les parenthèses sont obligatoires si vous initialisez le dict avec une clé de tuples, mais vous pouvez les omettre lors de la définition / obtention de valeurs à l'aide de []:

 mydict = {}                        # Initialized the dict
mydict['foo', 'bar', 'baz'] = 1    # Sets a value
mydict['foo', 'bar', 'baz']        # Returns 1
 

2voto

Dana Points 9876

Je suppose que la traduction littérale serait:

  mydict = {'foo' : { 'bar' : { 'baz':1}}}
 

Appel:

  >>> mydict['foo']['bar']['baz']
 

vous donne 1.

Cela me semble un peu grossier.

(Je ne suis pas un gars en Perl, alors je devine ce que fait votre Perl)

1voto

Tetha Points 2570

Les dictionnaires imbriqués comme celui-ci sont (souvent) appelés objets pauvres. Oui, il y a une implication et cela pourrait être en corrélation avec la nature orientée objet de pythons.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X