2009-02-23 2 views
297

Каков наилучший способ расширить словарь с помощью другого? Например:Python "extend" для словаря

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

Я ищу любую работу, чтобы получить это избежать for цикла:

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

Я желаю, чтобы сделать что-то вроде:

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

Я знал для списков [], тогда я могу использовать работу для других, а не extrange ;-) – FerranB

ответ

476
+3

После прочтения документов вы поймете, почему существует «обновление», но «нет». – georg

+13

Имейте в виду, что update() напрямую изменяет dict и возвращает None. – emisilva

+0

Но что, если вы хотите расширить dict только с значениями, которые уже не определены (то есть не переписывают существующие значения)? Например, обновите dict '{" a ": 2," b ": 3}' с dict '{" b ": 4," c ": 5}' to dict '{" a ": 2," b ": 3," С ": 5}'? Конечно, возможно использование 'update()' путем перемещения некоторого материала вокруг, но было бы лучше, если бы его можно было выполнить только в одной строке ... – Nearoo

20
a.update(b) 

Будут добавлены ключи и значения от b до a, переписывая, если уже есть значение для ключа.

136

красивый драгоценный камень в this closed question:

"Oneliner путь", изменяя ни один из входных dicts, является

basket = dict(basket_one, **basket_two) 

Узнайте, что **basket_two (the **) means here.

В случае возникновения конфликта предметы с basket_two переопределяют числа от basket_one. По мере того, как идут одни лайнеры, это довольно легко читаемо и прозрачно, и я не имею никакого отношения к тому, чтобы использовать его в любое время, когда диктуется смесь из двух других (любой читатель, у которого есть проблемы с пониманием, на самом деле будет очень хорошо обслуживаться как это побуждает его или ее к изучению dict и формы ** ;-). Так, например, такие как:

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

являются довольно частыми появлениями в моем коде.

Первоначально представленный Alex Martelli

Примечание: В Python 3, это будет работать только тогда, когда каждый ключ в basket_two является string.

+2

Документация для ['dict' ] (http://docs.python.org/2/library/stdtypes.html#dict) легко найти в то время как ['**'] (http://www.saltycrane.com/blog/2008/01/ как-к-use-args-and-kwargs-in-python /) немного сложнее (ключевое слово - * kwargs *). Вот хорошее объяснение: http://www.saltycrane.com/blog/2008/01/how-to-use-args-and-kwargs-in-python/ – johndodo

+1

это может быть использовано для создания второй переменной с single command, тогда как 'basket_one.update ()', как сказано в названии, обновляет существующий словарь (или клонированный). – furins

+1

Обратите внимание, что в Python 3 имена аргументов и, следовательно, ключи '** anotherdict' должны быть строками. –

15

Как уже упоминалось, a.update(b) для некоторых dicts a и b добьетесь результата вы просили в вашем вопросе. Тем не менее, я хочу отметить, что много раз я видел метод сопоставления/установки объектов , что в синтаксисе a.extend(b) значения a НЕ должны быть перезаписаны значениями b. a.update(b) перезаписывает значения a, и поэтому это не очень хороший выбор для extend.

Обратите внимание, что некоторые языки называют этот метод defaults или inject, поскольку его можно рассматривать как способ введения значений b (которые могут быть набором значений по умолчанию) в словарь без перезаписи значений, которые могут уже существовать.

Конечно, вы могли бы просто отметить, что a.extend(b) практически не отличается от b.update(a); a=b.Чтобы удалить задание, вы можете сделать это таким образом:

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) 

Благодаря Тому Лейс для этой умной идеей с использованием побочных эффектов менее dict конструктор extend.