Python "расширить" для словаря - PullRequest
387 голосов
/ 23 февраля 2009

Какой лучший способ расширить словарь другим? Например:

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

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

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

Я хочу сделать что-то вроде:

a.extend(b)  # This does not work

Ответы [ 6 ]

598 голосов
/ 23 февраля 2009
166 голосов
/ 12 октября 2009

Красивая жемчужина в этот закрытый вопрос :

«Единый путь», не изменяющий ни один из входных диктов, равен

basket = dict(basket_one, **basket_two)

Узнайте, что **basket_two (**) означает здесь .

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

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

- это довольно частые случаи в моем коде.

Первоначально представленный Алекс Мартелли

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

27 голосов
/ 03 июля 2018

Вы пытались использовать словарное понимание со словарным отображением:

c = {**a, **b}
# c = { "a" : 1, "b" : 2, "c" : 3, "d" : 4 }
23 голосов
/ 23 февраля 2009
a.update(b)

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

17 голосов
/ 02 октября 2012

Как уже упоминали другие, a.update(b) для некоторых диктов a и b приведет к результату, который вы просили в своем вопросе. Однако я хочу отметить, что много раз я видел, как extend метод отображения / установки объектов желал, чтобы в синтаксисе 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.

0 голосов
/ 25 апреля 2019

Вы также можете использовать Python collection.Chainmap , который был представлен в Python 3.3.

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

Это имеет несколько возможных преимуществ, в зависимости от вашего варианта использования. Они объясняются более подробно здесь , но я дам краткий обзор:

  • Цепная карта использует только представления словарей, поэтому данные фактически не копируются. Это приводит к более быстрому сцеплению (но более медленному поиску)
  • На самом деле никакие ключи не перезаписываются, поэтому при необходимости вы знаете, поступают ли данные с a или b.

Это в основном делает его полезным для таких вещей, как словари конфигурации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...