Python“扩展”字典

问题:Python“扩展”字典

扩展词典与另一本词典的最佳方法是什么?例如:

>>> 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

Which is the best way to extend a dictionary with another one? For instance:

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

I’m looking for any operation to obtain this avoiding for loop:

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

I wish to do something like:

a.extend(b)  # This does not work

回答 0


回答 1

这个封闭的问题中的一颗美丽的宝石:

“单一方式”,既不改变输入命令,也不改变

basket = dict(basket_one, **basket_two)

了解什么是**basket_two(在**)指这里

如果发生冲突,来自的项目basket_two将覆盖来自的项目basket_one。就像一线书一样,这是很容易理解和透明的,并且我不反对在任何时候都可以方便地使用由其他两种方法混合而成的字典(实际上,任何理解它的读者都会得到很好的服务)顺便这促使他或她对学习dict**形式;-)。因此,例如,使用如下:

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

在我的代码中相当频繁地出现。

最初由Alex Martelli提交

注意:在Python 3中,只有在basket_two中的每个键都是a的情况下,这才起作用string

A beautiful gem in this closed question:

The “oneliner way”, altering neither of the input dicts, is

basket = dict(basket_one, **basket_two)

Learn what **basket_two (the **) means here.

In case of conflict, the items from basket_two will override the ones from basket_one. As one-liners go, this is pretty readable and transparent, and I have no compunction against using it any time a dict that’s a mix of two others comes in handy (any reader who has trouble understanding it will in fact be very well served by the way this prompts him or her towards learning about dict and the ** form;-). So, for example, uses like:

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

are reasonably frequent occurrences in my code.

Originally submitted by Alex Martelli

Note: In Python 3, this will only work if every key in basket_two is a string.


回答 2

您是否尝试过将字典理解与字典映射一起使用:

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

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

另一种方法是通过使用dict(iterable,** kwarg)

c = dict(a, **b)
# c = {'a': 1, 'b': 2, 'c': 3, 'd': 4}

在Python 3.9中,您可以使用union | 算子

# use the merging operator |
c = a | b
# c = {'a': 1, 'b': 2, 'c': 3, 'd': 4}

Have you tried using dictionary comprehension with dictionary mapping:

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

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

Another way of doing is by Using dict(iterable, **kwarg)

c = dict(a, **b)
# c = {'a': 1, 'b': 2, 'c': 3, 'd': 4}

In Python 3.9 you can add two dict using union | operator

# use the merging operator |
c = a | b
# c = {'a': 1, 'b': 2, 'c': 3, 'd': 4}

回答 3

a.update(b)

将键和值从b添加到a,如果键已经存在,则覆盖。

a.update(b)

Will add keys and values from b to a, overwriting if there’s already a value for a key.


回答 4

正如其他人提到的那样,a.update(b)对于某些命令而言ab它将达到您在问题中所要求的结果。但是,我想指出的是,我多次看到extend映射/设置对象的方法希望在语法中a.extend(b)a的值不应被b的值覆盖。a.update(b)会覆盖a的值,因此不是的理想选择extend

请注意,某些语言将这种方法称为defaultsinject,因为可以将其视为将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)

感谢Tom Leys提出的巧妙想法,它使用的无副作用dict构造函数extend

As others have mentioned, a.update(b) for some dicts a and b will achieve the result you’ve asked for in your question. However, I want to point out that many times I have seen the extend method of mapping/set objects desire that in the syntax a.extend(b), a‘s values should NOT be overwritten by b‘s values. a.update(b) overwrites a‘s values, and so isn’t a good choice for extend.

Note that some languages call this method defaults or inject, as it can be thought of as a way of injecting b’s values (which might be a set of default values) in to a dictionary without overwriting values that might already exist.

Of course, you could simple note that a.extend(b) is nearly the same as b.update(a); a=b. To remove the assignment, you could do it thus:

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)

Thanks to Tom Leys for that smart idea using a side-effect-less dict constructor for extend.


回答 5

您还可以使用python 3.3中引入的python的collections.Chainmap

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

根据您的用例,这有一些可能的优点。这里将对它们进行更详细的说明,但我将做一个简要概述:

  • 链图仅使用词典的视图,因此实际上没有数据被复制。这样可以加快链接速度(但查找速度较慢)
  • 实际上没有键被覆盖,因此,如有必要,您可以知道数据是来自a还是来自b。

这主要使其对于诸如配置字典之类的事情有用。

You can also use python’s collections.Chainmap which was introduced in python 3.3.

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

This has a few possible advantages, depending on your use-case. They are explained in more detail here, but I’ll give a brief overview:

  • A chainmap only uses views of the dictionaries, so no data is actually copied. This results in faster chaining (but slower lookup)
  • No keys are actually overwritten so, if necessary, you know whether the data comes from a or b.

This mainly makes it useful for things like configuration dictionaries.


回答 6

如果您需要将其作为Class,则可以使用dict扩展它并使用update方法:

Class a(dict):
  # some stuff
  self.update(b)

In case you need it as a Class, you can extend it with dict and use update method:

Class a(dict):
  # some stuff
  self.update(b)