web-dev-qa-db-fra.com

Python "extend" pour un dictionnaire

Quel est le meilleur moyen d'étendre un dictionnaire avec un autre? Par exemple:

>>> a = { "a" : 1, "b" : 2 }
>>> b = { "c" : 3, "d" : 4 }
>>> a
{'a': 1, 'b': 2}
>>> b
{'c': 3, 'd': 4}

Je cherche toute opération pour obtenir cette boucle évitant for:

{ "a" : 1, "b" : 2, "c" : 3, "d" : 4 }

Je souhaite faire quelque chose comme:

a.extend(b)  # This does not work
396
FerranB
619
Nick Fortescue

Un beau bijou dans cette question fermée :

La "voie unique", qui ne modifie aucun des dict d’entrée, est

basket = dict(basket_one, **basket_two)

Apprenez ce que **basket_two (le **) signifie ici .

En cas de conflit, les éléments de basket_two remplaceront ceux de basket_one. En une seule ligne, c'est assez lisible et transparent, et je n'ai rien contre de l'utiliser chaque fois qu'un dicton mélangeant deux autres est utile (tout lecteur qui a du mal à comprendre cela sera en fait très bien servi par la façon dont cela le pousse à en savoir plus sur dict et le ** formulaire ;-). Ainsi, par exemple, utilise comme:

x = mungesomedict(dict(adict, **anotherdict))

sont des occurrences assez fréquentes dans mon code.

Soumis à l'origine par Alex Martelli

Remarque: Dans Python 3, cela ne fonctionnera que si chaque clé de basket_two est une string.

171
Tom Leys

Avez-vous essayé d'utiliser la compréhension de dictionnaire avec la cartographie de dictionnaire:

c = {**a, **b}
# c = { "a" : 1, "b" : 2, "c" : 3, "d" : 4 }
30
Vlad Bezden
a.update(b)

Ajoutera des clés et des valeurs de b à a, en écrasant s'il existe déjà une valeur pour une clé.

24
vartec

Comme d'autres l'ont mentionné, a.update(b) pour certains dict a et b donnera le résultat que vous avez demandé dans votre question. Cependant, je tiens à souligner que j'ai souvent vu la méthode extend de mappage/définir des objets souhaite que, dans la syntaxe a.extend(b), les valeurs de a NE soient PAS écrasées par les valeurs de b. a.update(b) écrase les valeurs de a et n'est donc pas un bon choix pour extend.

Notez que certaines langues appellent cette méthode defaults ou inject, car elle peut être considérée comme un moyen d'injecter les valeurs de b (qui peuvent être un ensemble de valeurs par défaut) dans un dictionnaire sans écraser les valeurs existantes.

Bien sûr, vous pouvez simplement noter que a.extend(b) est presque identique à b.update(a); a=b. Pour supprimer la tâche, vous pouvez le faire comme suit:

def extend(a,b):
    """Create a new dictionary with a's properties extended by b,
    without overwriting.

    >>> extend({'a':1,'b':2},{'b':3,'c':4})
    {'a': 1, 'c': 4, 'b': 2}
    """
    return dict(b,**a)

Merci à Tom Leys pour cette idée intelligente qui utilise un constructeur _dict sans effet secondaire pour extend.

17
eblume

Vous pouvez également utiliser collections.Chainmap de python, introduit dans python 3.3.

from collections import Chainmap
c = Chainmap(a, b)
c['a'] # returns 1

Cela présente quelques avantages possibles, selon votre cas d'utilisation. Ils sont expliqués plus en détail ici , mais je vais donner un bref aperçu:

  • Une mappe n'utilise que les vues des dictionnaires, de sorte qu'aucune donnée n'est réellement copiée. Cela se traduit par un chaînage plus rapide (mais une recherche plus lente)
  • Aucune clé n'est en réalité écrasée. Ainsi, si nécessaire, vous savez si les données proviennent de a ou de b.

Cela le rend principalement utile pour des choses comme les dictionnaires de configuration.

1
Ivo Merchiers