web-dev-qa-db-fra.com

Python erreur de clé de dictionnaire lors de l'affectation - comment puis-je contourner ce problème?

J'ai un dictionnaire que je crée comme ceci:

myDict = {}

Ensuite, j'aime y ajouter une clé qui correspond à un autre dictionnaire, dans lequel je mets une autre valeur:

myDict[2000]['hello'] = 50

Alors quand je passe myDict[2000]['hello'] quelque part, cela donnerait 50.

Pourquoi n'est-ce pas Python juste créer ces entrées là? Quel est le problème? Je pensais que KeyError ne se produit que lorsque vous essayez de lire une entrée qui n'existe pas, mais je la crée correctement ici?

20
ulak blade

KeyError se produit parce que vous essayez de lire une clé inexistante lorsque vous essayez d'accéder à myDict[2000]. Comme alternative, vous pouvez utiliser defaultdict :

>>> from collections import defaultdict
>>> myDict = defaultdict(dict)
>>> myDict[2000]['hello'] = 50
>>> myDict[2000]
{'hello': 50}

defaultdict(dict) signifie que si myDict rencontre une clé inconnue, il retournera une valeur par défaut, dans ce cas, tout ce qui est retourné par dict () qui est un dictionnaire vide.

23
OldGeeksGuide

Mais vous êtes en train de lire une entrée qui n'existe pas: myDict[2000].

La traduction exacte de ce que vous dites dans votre code est "donnez-moi l'entrée dans myDict avec la clé de 2000 et stockez 50 contre la clé" bonjour "dans cette entrée." Mais myDict n'a pas de clé de 2000, d'où l'erreur.

Ce que vous devez réellement faire, c'est créer cette clé. Vous pouvez le faire en une seule fois:

myDict[2000] = {'hello': 50}
7
Daniel Roseman

Ce que vous voulez, c'est implémenter un dict imbriqué :

Je recommande cette approche:

class Vividict(dict):
    def __missing__(self, key):
        value = self[key] = type(self)()
        return value

Depuis la documentation, sous d[key]

Nouveau dans la version 2.5: si une sous-classe de dict définit une méthode __missing__(), si la clé key n'est pas présente, l'opération d [clé] appelle cette méthode avec la clé clé comme argument

Pour l'essayer:

myDict = Vividict()

myDict[2000]['hello'] = 50

et myDict retourne maintenant:

{2000: {'hello': 50}}

Et cela fonctionnera pour n'importe quelle profondeur arbitraire que vous souhaitez:

myDict['foo']['bar']['baz']['quux']

fonctionne juste.

4
Aaron Hall

Vous avez raison, mais dans votre code python doit d'abord récupérer myDict [2000] puis faire l'affectation. Comme cette entrée n'existe pas, elle ne peut pas être affectée à ses éléments

1