2009-02-23 11 views
297

Quelle est la meilleure façon d'étendre un dictionnaire avec un autre? Par exemple:Python "étendre" pour un dictionnaire

>>> 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 ce qui évite la boucle for:

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

Je veux faire quelque chose comme:

a.extend(b) # This does not work 
+22

Je savais pour les listes [], alors je suppose que cela peut être du travail pour les autres, pas extrange ;-) – FerranB

Répondre

476
+3

Après avoir lu les docs, on comprendra pourquoi il y a un'update 'mais pas'extend'. – georg

+13

Gardez à l'esprit que update() modifie directement la dict et renvoie None. – emisilva

+0

Mais que se passe-t-il si vous souhaitez uniquement étendre la dict avec des valeurs qui ne sont pas déjà définies (c'est-à-dire ne pas écraser les valeurs existantes)? Par exemple, mettez à jour un dict '{" a ": 2," b ": 3}' avec dict '{" b ": 4," c ": 5}' pour imposer '{" a ": 2," b ": 3," c ": 5}'? Bien sûr, il est possible d'utiliser 'update()' en déplaçant certaines choses, mais ce serait plus agréable si cela pouvait être accompli en une seule ligne ... – Nearoo

20
a.update(b) 

ajoutera les clés et les valeurs de b-un, il y a si écrasant déjà une valeur pour une clé.

136

Un beau joyau this closed question:

La "façon oneliner", modifier ni des dicts d'entrée, est

basket = dict(basket_one, **basket_two) 

savoir ce **basket_two (the **) means here. En cas de conflit, les articles de basket_two remplaceront ceux de basket_one. En un coup d'œil, c'est assez lisible et transparent, et je n'ai aucun scrupule à l'utiliser à chaque fois qu'un dict qui est un mélange de deux autres est très pratique (tout lecteur qui a du mal à comprendre sera très bien servi par la façon dont cela l'incite à apprendre à propos de dict et le formulaire ** ;-). Ainsi, par exemple, utilise comme:

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

sont des occurrences raisonnablement fréquentes dans mon code.

présenté à l'origine par Alex Martelli

Note: En Python 3, cela ne fonctionnera que si toutes les clés dans basket_two est un string.

+2

Documentation pour ['dict' ] (http://docs.python.org/2/library/stdtypes.html#dict) est facile à trouver lorsque ['**'] (http://www.saltycrane.com/blog/2008/01/ how-to-use-args-et-kwargs-in-python /) est un peu plus compliqué (le mot clé est * kwargs *). Voici une bonne explication: http://www.saltycrane.com/blog/2008/01/how-to-use-args-and-kwargs-in-python/ – johndodo

+1

cela peut être utilisé pour générer une deuxième variable avec un commande unique, alors que 'basket_one.update ()' comme son nom l'indique, met à jour un dictionnaire existant (ou un dictionnaire cloné). – furins

+1

Notez que dans Python 3, les noms d'arguments, et donc les clés de '** anotherdict', doivent être des chaînes. –

15

Comme d'autres l'ont mentionné, a.update(b) pour certains dicts a et b permettra d'atteindre le résultat que vous avez demandé à votre question. Cependant, je tiens à souligner que de nombreuses fois, j'ai vu la méthode extend d'objets mapping/set désir que dans la syntaxe a.extend(b), a « s valeurs ne doivent PAS être remplacées par b » s valeurs. a.update(b) remplace les valeurs a et n'est donc pas un bon choix pour extend. Notez que certaines langues appellent cette méthode defaults ou inject, car cela peut être considéré comme un moyen d'injecter dans un dictionnaire des valeurs de b (qui peuvent être un ensemble de valeurs par défaut) sans écraser les valeurs qui pourraient déjà exister.

Bien sûr, vous pouvez simplement noter que a.extend(b) est presque le même que b.update(a); a=b.Pour supprimer l'affectation, vous pouvez le faire ainsi:

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 à puce en utilisant un constructeur effet secondaire-moins dict pour extend.