如何在一个expression式中合并两个字典?

我有两个Python字典,我想写一个expression式,返回这两个字典,合并。 update()方法将是我所需要的,如果它返回的结果,而不是就地修改字典。

 >>> x = {'a':1, 'b': 2} >>> y = {'b':10, 'c': 11} >>> z = x.update(y) >>> print(z) None >>> x {'a': 1, 'b': 10, 'c': 11} 

我怎么能得到最后的合并字典在z ,而不是x

(为了更加清楚, dict.update()的最后一个冲突处理也是我正在寻找的。)

    我怎样才能在一个expression式中合并两个Python字典?

    对于字典xyz变成一个合并字典,其中y值取代了x

    • 在Python 3.5或更高版本中,:

       z = {**x, **y} 
    • 在Python 2中,(或者3.4或者更低)写一个函数:

       def merge_two_dicts(x, y): z = x.copy() # start with x's keys and values z.update(y) # modifies z with y's keys and values & returns None return z 

       z = merge_two_dicts(x, y) 

    说明

    假设你有两个词典,你想把它们合并成一个新的词典而不改变原来的词典:

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

    所需的结果是得到一个新的字典( z )的值合并,第二个字典的值覆盖了第一个。

     >>> z {'a': 1, 'b': 3, 'c': 4} 

    PEP 448中提出了一个新的语法, 可以从Python 3.5中获得

     z = {**x, **y} 

    这确实是一个单一的expression。 现在它已经在3.5,PEP 478的发布时间表中显示出来了,现在它已经进入了Python 3.5文档中的新function 。

    但是,由于许多组织仍在使用Python 2,因此您可能希望以向后兼容的方式进行操作。 Python 2和Python 3.0-3.4中提供的经典Pythonic方法是将其作为一个两步过程来完成:

     z = x.copy() z.update(y) # which returns None since it mutates z 

    在这两种方法中, y都是次要的,它的值将取代x的值,因此在我们的最终结果中'b'将指向3

    还没有在Python 3.5上,但想要一个expression式

    如果您还没有使用Python 3.5,或者需要编写向后兼容的代码,并且希望在单个expression式中使用 ,那么正确的方法是将其放在一个函数中:

     def merge_two_dicts(x, y): """Given two dicts, merge them into a new dict as a shallow copy.""" z = x.copy() z.update(y) return z 

    然后你有一个单一的expression式:

     z = merge_two_dicts(x, y) 

    你也可以创build一个函数来合并一个从零到非常大的数字的未定义的字符:

     def merge_dicts(*dict_args): """ Given any number of dicts, shallow copy and merge into a new dict, precedence goes to key value pairs in latter dicts. """ result = {} for dictionary in dict_args: result.update(dictionary) return result 

    这个函数将在Python 2和3中适用于所有的字典。 例如给定的口令ag

     z = merge_dicts(a, b, c, d, e, f, g) 

    并且g键值对将优先于af等等。

    对其他答案的批评

    不要使用以前接受的答案中看到的内容:

     z = dict(x.items() + y.items()) 

    在Python 2中,为每个字典在内存中创build两个列表,在内存中创build第三个列表,长度等于前两个列表的长度,然后放弃所有三个列表来创build字典。 在Python 3中,这会失败,因为您将两个dict_items对象添加dict_items一起,而不是两个列表 –

     >>> c = dict(a.items() + b.items()) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for +: 'dict_items' and 'dict_items' 

    你必须明确地创build它们作为列表,例如z = dict(list(x.items()) + list(y.items())) 。 这是资源和计算能力的浪费。

    类似的,当Python 3中的items() viewitems() Python 2.7中的viewitems()中的items()的联合时,当值不可对象(例如列表)时也会失败。 即使你的值是可散列的, 由于集合在语义上是无序的,所以关于优先级的行为是未定义的。 所以不要这样做:

     >>> c = dict(a.items() | b.items()) 

    这个例子演示了值不可用时会发生什么:

     >>> x = {'a': []} >>> y = {'b': []} >>> dict(x.items() | y.items()) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unhashable type: 'list' 

    下面是一个例子,其中y应该优先,但是由于集合的任意顺序,x的值被保留:

     >>> x = {'a': 2} >>> y = {'a': 1} >>> dict(x.items() | y.items()) {'a': 2} 

    另一个黑客,你不应该使用:

     z = dict(x, **y) 

    这使用了dict构造函数,而且速度和内存都非常快(甚至比我们的两步过程稍微多一些),但除非您确切地知道这里发生了什么(也就是说,第二个字典是作为关键字parameter passing给字典构造函数),它很难阅读,这不是预期的用法,所以它不是Pythonic。

    以下是django中正在使用的一个例子。

    字典意图采用可哈希键(例如frozensets或tuples),但是当这个键不是string时这个方法在Python 3中失败了。

     >>> c = dict(a, **b) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: keyword arguments must be strings 

    在邮件列表中 ,该语言的创build者Guido van Rossum写道:

    我认为dict({},** {1:3})是非法的,因为毕竟是滥用**机制。

    显然,dict(x,** y)正在为“调用x.update(y)并返回x”作为“cool hack”。 我个人觉得它比酷酷的更卑劣。

    这是我的理解(以及对语言创build者的理解), dict(**y)的预期用法是为了可读性目的创build字典,例如:

     dict(a=1, b=10, c=11) 

    代替

     {'a': 1, 'b': 10, 'c': 11} 

    回应评论

    尽pipeGuido说, dict(x, **y)符合字典规范,这顺便说一句。 适用于Python 2和Python 3.这仅适用于string键的事实是关键字参数如何工作的直接结果,而不是dict的短暂结果。 在这个地方也没有使用**运算符来滥用这个机制,实际上**的devise恰恰是把关键字作为关键字来传递的。

    同样,当键不是string时,它不能用于3。 隐式调用约定是命名空间采用普通的字典,而用户只能传递string的关键字参数。 所有其他可调用的强制执行它。 dict在Python 2中打破了这种一致性:

     >>> foo(**{('a', 'b'): None}) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: foo() keywords must be strings >>> dict(**{('a', 'b'): None}) {('a', 'b'): None} 

    Python的其他实现(Pypy,Jython,IronPython)导致了这种不一致。 因此它在Python 3中被修复,因为这个用法可能是一个突破性的改变。

    我向你提出,故意编写只能在一种语言版本中工作的代码,或者只能在某些特定的约束条件下才能工作,这是恶意的无能。

    另一评论:

    dict(x.items() + y.items())仍然是Python 2最可读的解决scheme。可读性计数。

    我的回应: merge_two_dicts(x, y)实际上对我来说似乎更加清晰,如果我们真的关心可读性的话。 它不是向前兼容的,因为Python 2日益被弃用。

    性能较差,但正确的临时性

    这些方法性能较差,但会提供正确的行为。 与copyupdate或新的解包相比,它们的性能要差得多,因为它们在更高级别的抽象层次上遍历每个键值对,但是它们确实遵循优先顺序(后面的字典有优先级)

    您也可以在dict理解中手动链接dicts:

     {k: v for d in dicts for k, v in d.items()} # iteritems in Python 2.7 

    或者在Python 2.6中(也许早在引入生成器expression式时就是2.4):

     dict((k, v) for d in dicts for k, v in d.items()) 

    itertools.chain会按照正确的顺序将迭代器链接到键值对上:

     import itertools z = dict(itertools.chain(x.iteritems(), y.iteritems())) 

    性能分析

    我只会做已知行为正确的用法的性能分析。

     import timeit 

    以下是在Ubuntu 14.04上完成的

    在Python 2.7(系统Python)中:

     >>> min(timeit.repeat(lambda: merge_two_dicts(x, y))) 0.5726828575134277 >>> min(timeit.repeat(lambda: {k: v for d in (x, y) for k, v in d.items()} )) 1.163769006729126 >>> min(timeit.repeat(lambda: dict(itertools.chain(x.iteritems(), y.iteritems())))) 1.1614501476287842 >>> min(timeit.repeat(lambda: dict((k, v) for d in (x, y) for k, v in d.items()))) 2.2345519065856934 

    在Python 3.5(deadsnakes PPA)中:

     >>> min(timeit.repeat(lambda: {**x, **y})) 0.4094954460160807 >>> min(timeit.repeat(lambda: merge_two_dicts(x, y))) 0.7881555100320838 >>> min(timeit.repeat(lambda: {k: v for d in (x, y) for k, v in d.items()} )) 1.4525277839857154 >>> min(timeit.repeat(lambda: dict(itertools.chain(x.items(), y.items())))) 2.3143140770262107 >>> min(timeit.repeat(lambda: dict((k, v) for d in (x, y) for k, v in d.items()))) 3.2069112799945287 

    词典资源

    • 我对Python的字典实现的解释,更新为3.6。
    • 回答如何将新密钥添加到字典中
    • 将两个列表映射到一个字典中
    • 官方Python 文档的字典
    • 词典甚至更强大 – 在2017年Pycon上Brandon Rhodes的谈话
    • 现代Python词典,一个伟大想法的汇合 – Raymond Hettinger在Pycon 2017上的发言

    就你而言,你可以做的是:

     z = dict(x.items() + y.items()) 

    这将根据你的需要在zinput最后一个字典,并使第二个字母( y )的值正确地覆盖键b的值:

     >>> x = {'a':1, 'b': 2} >>> y = {'b':10, 'c': 11} >>> z = dict(x.items() + y.items()) >>> z {'a': 1, 'c': 11, 'b': 10} 

    如果你使用Python 3,它只是更复杂一点。 要创buildz

     >>> z = dict(list(x.items()) + list(y.items())) >>> z {'a': 1, 'c': 11, 'b': 10} 

    替代:

     z = x.copy() z.update(y) 

    另一个更简洁的选项:

     z = dict(x, **y) 

    注意 :这已经成为一个stream行的答案,但重要的是要指出,如果y有任何非string键,这个工作的事实就是滥用CPython实现细节,并且在Python 3中不起作用,或者在PyPy,IronPython或者Jython中。 另外, Guido不是粉丝 。 所以我不能推荐这种技术用于向前兼容或跨实现的可移植代码,这实际上意味着它应该完全避免。

    这可能不是一个stream行的答案,但你几乎肯定不想这样做。 如果你想要一个合并的副本,然后使用复制(或深度复制,取决于你想要的),然后更新。 这两行代码比使用.items()+ .items()创build的单行更可读 – Pythonic更多。 显式比隐式更好。

    另外,当你使用.items()(在Python 3.0之前)时,你正在创build一个包含字典项目的新列表。 如果你的字典很大,那么这是相当多的开销(两个大的列表,只要合并字典被创build就会被扔掉)。 update()可以更高效地工作,因为它可以逐个运行第二个字典。

    在时间方面 :

     >>> timeit.Timer("dict(x, **y)", "x = dict(zip(range(1000), range(1000)))\ny=dict(zip(range(1000,2000), range(1000,2000)))").timeit(100000) 15.52571702003479 >>> timeit.Timer("temp = x.copy()\ntemp.update(y)", "x = dict(zip(range(1000), range(1000)))\ny=dict(zip(range(1000,2000), range(1000,2000)))").timeit(100000) 15.694622993469238 >>> timeit.Timer("dict(x.items() + y.items())", "x = dict(zip(range(1000), range(1000)))\ny=dict(zip(range(1000,2000), range(1000,2000)))").timeit(100000) 41.484580039978027 

    国际海事组织前两个之间的小幅放缓是值得的可读性。 此外,字典创build的关键字参数仅在Python 2.3中添加,而copy()和update()将在旧版本中使用。

    在后续的答案中,你问到了这两个select的相对performance:

     z1 = dict(x.items() + y.items()) z2 = dict(x, **y) 

    在我的机器上,至less(一个相当普通的运行Python 2.5.2的x86_64),替代的z2不仅更简单,而且速度更快。 您可以使用Python自带的timeit模块来validation这一点。

    示例1:相同的字典将20个连续的整数映射到它们自己:

     % python -m timeit -s 'x=y=dict((i,i) for i in range(20))' 'z1=dict(x.items() + y.items())' 100000 loops, best of 3: 5.67 usec per loop % python -m timeit -s 'x=y=dict((i,i) for i in range(20))' 'z2=dict(x, **y)' 100000 loops, best of 3: 1.53 usec per loop 

    z2赢得3.5倍左右。 不同的字典似乎有不同的结果,但z2似乎总是出来。 (如果在相同的testing中得到不一致的结果,请尝试将大于默认值3的数字传入-r 。)

    示例2:非重叠字典将252个短string映射到整数,反之亦然:

     % python -m timeit -s 'from htmlentitydefs import codepoint2name as x, name2codepoint as y' 'z1=dict(x.items() + y.items())' 1000 loops, best of 3: 260 usec per loop % python -m timeit -s 'from htmlentitydefs import codepoint2name as x, name2codepoint as y' 'z2=dict(x, **y)' 10000 loops, best of 3: 26.9 usec per loop 

    z2大约是10倍。这是我的书中一个非常大的胜利!

    在比较这两个项目后,我想知道z1的糟糕performance是否可以归因于构build两个项目列表的开销,这反过来又让我怀疑这种变化是否可能更好:

     from itertools import chain z3 = dict(chain(x.iteritems(), y.iteritems())) 

    一些快速testing,例如

     % python -m timeit -s 'from itertools import chain; from htmlentitydefs import codepoint2name as x, name2codepoint as y' 'z3=dict(chain(x.iteritems(), y.iteritems()))' 10000 loops, best of 3: 66 usec per loop 

    导致我得出结论: z3z1快一些,但几乎不如z2快。 绝对不值得所有额外的打字。

    这个讨论仍然缺less一些重要的东西,这些东西是将这些替代品与“显而易见”的合并两个列表的方式进行性能比较:使用update方法。 为了尽量保持与expression式平等的地位,其中没有一个修改x或y,我将复制x而不是就地修改它,如下所示:

     z0 = dict(x) z0.update(y) 

    典型的结果是:

     % python -m timeit -s 'from htmlentitydefs import codepoint2name as x, name2codepoint as y' 'z0=dict(x); z0.update(y)' 10000 loops, best of 3: 26.9 usec per loop 

    换句话说, z0z2似乎具有基本相同的性能。 你觉得这可能是巧合吗? 我不….

    事实上,我甚至可以声称纯Python代码不可能做得比这更好。 如果你可以在C扩展模块中做得更好,我想Python的人可能会把你的代码(或者你的方法的一个变体)整合到Python核心中。 Python在很多地方使用dict ; 优化运营是一件大事。

    你也可以这样写

     z0 = x.copy() z0.update(y) 

    正如托尼所做的那样,但是(不足为奇),表示法的差别不会对性能产生任何可衡量的影响。 使用任何看起来正确的给你。 当然,他是完全正确的,指出双语版本更容易理解。

    我想要类似的东西,但能够指定重复键上的值如何合并,所以我砍掉了这个(但没有严重testing它)。 显然这不是一个expression式,而是一个单一的函数调用。

     def merge(d1, d2, merge_fn=lambda x,y:y): """ Merges two dictionaries, non-destructively, combining values on duplicate keys as defined by the optional merge function. The default behavior replaces the values in d1 with corresponding values in d2. (There is no other generally applicable merge strategy, but often you'll have homogeneous types in your dicts, so specifying a merge technique can be valuable.) Examples: >>> d1 {'a': 1, 'c': 3, 'b': 2} >>> merge(d1, d1) {'a': 1, 'c': 3, 'b': 2} >>> merge(d1, d1, lambda x,y: x+y) {'a': 2, 'c': 6, 'b': 4} """ result = dict(d1) for k,v in d2.iteritems(): if k in result: result[k] = merge_fn(result[k], v) else: result[k] = v return result 

    在Python 3中,您可以使用collections.ChainMap将多个字典或其他映射组合在一起,以创build一个可更新的视图:

     >>> from collections import ChainMap >>> x = {'a':1, 'b': 2} >>> y = {'b':10, 'c': 11} >>> z = ChainMap({}, y, x) >>> for k, v in z.items(): print(k, '-->', v) a --> 1 b --> 10 c --> 11 

    我能想到的最好的版本,而不使用复制将是:

     from itertools import chain x = {'a':1, 'b': 2} y = {'b':10, 'c': 11} dict(chain(x.iteritems(), y.iteritems())) 

    它比dict(x.items() + y.items())快,但不如n = copy(a); n.update(b) n = copy(a); n.update(b) ,至less在CPython上。 如果将iteritems()更改为items() ,则此版本也可以在Python 3中运行,这是由2to3工具自动完成的。

    就我个人而言,我最喜欢这个版本,因为它在单个函数语法中描述的相当不错。 唯一的小问题是,y的值优先于x的值并不能完全显而易见,但我不认为很难弄明白。

    recursion/深度更新字典

     def deepupdate(original, update): """ Recursively update a dict. Subdict's won't be overwritten but also updated. """ for key, value in original.iteritems(): if key not in update: update[key] = value elif isinstance(value, dict): deepupdate(value, update[key]) return update 

    示范:

     pluto_original = { 'name': 'Pluto', 'details': { 'tail': True, 'color': 'orange' } } pluto_update = { 'name': 'Pluutoo', 'details': { 'color': 'blue' } } print deepupdate(pluto_original, pluto_update) 

    输出:

     { 'name': 'Pluutoo', 'details': { 'color': 'blue', 'tail': True } } 

    谢谢修改。

     x = {'a':1, 'b': 2} y = {'b':10, 'c': 11} z = dict(x.items() + y.items()) print z 

    对于在这两个字典('b')中都有键的项目,可以通过放置最后一个来控制输出中哪一个结束。

    Python 3.5(PEP 448)允许更好的语法选项:

     x = {'a': 1, 'b': 1} y = {'a': 2, 'c': 2} final = {**x, **y} final # {'a': 2, 'b': 1, 'c': 2} 

    甚至

     final = {'a': 1, 'b': 1, **x, **y} 

    虽然这个问题已经被多次回答了,但这个问题的简单解决方法还没有被列出。

     x = {'a':1, 'b': 2} y = {'b':10, 'c': 11} z4 = {} z4.update(x) z4.update(y) 

    它和z0和上面提到的z2一样快,但容易理解和改变。

     def dict_merge(a, b): c = a.copy() c.update(b) return c new = dict_merge(old, extras) 

    在这样阴暗而可疑的答案中,这个光辉的例子是合并Python中的字典的独一无二的好方法,由独裁者Guido van Rossum亲自批准! 其他人build议的一半,但没有把它放在一个函数。

     print dict_merge( {'color':'red', 'model':'Mini'}, {'model':'Ferrari', 'owner':'Carl'}) 

    得到:

     {'color': 'red', 'owner': 'Carl', 'model': 'Ferrari'} 

    如果你认为lambdas是邪恶的,那就不要再读了。 根据要求,您可以使用一个expression式来编写快速且高效的内存解决scheme:

     x = {'a':1, 'b':2} y = {'b':10, 'c':11} z = (lambda a, b: (lambda a_copy: a_copy.update(b) or a_copy)(a.copy()))(x, y) print z {'a': 1, 'c': 11, 'b': 10} print x {'a': 1, 'b': 2} 

    如上所述,使用两行或编写函数可能是更好的方法。

    在python3中, items方法不再返回一个列表 ,而是一个看起来像一个集合。 在这种情况下,你将需要采取设置联合,因为连接+将无法正常工作:

     dict(x.items() | y.items()) 

    对于版本2.7中的类似python3的行为, viewitems方法应该能够代替items

     dict(x.viewitems() | y.viewitems()) 

    无论如何,我更喜欢这种表示法,因为把它看作是一个联合操作而不是连接(如标题所示)似乎更自然。

    编辑:

    首先,请注意,除非y中的键是string,否则dict(x, **y)技巧在Python 3中将不起作用。

    此外,Raymond Hettinger的Chainmap 答案是非常优雅的,因为它可以将任意数量的string作为参数,但是从文档看来,它依次查看每个查找的所有字典列表:

    查找顺序search底层映射,直到find密钥。

    如果您在应用程序中进行了大量查找,这可能会降低速度:

     In [1]: from collections import ChainMap In [2]: from string import ascii_uppercase as up, ascii_lowercase as lo; x = dict(zip(lo, up)); y = dict(zip(up, lo)) In [3]: chainmap_dict = ChainMap(y, x) In [4]: union_dict = dict(x.items() | y.items()) In [5]: timeit for k in union_dict: union_dict[k] 100000 loops, best of 3: 2.15 µs per loop In [6]: timeit for k in chainmap_dict: chainmap_dict[k] 10000 loops, best of 3: 27.1 µs per loop 

    所以查找速度要慢一个数量级。 我是链接地图的粉丝,但在可能有很多查找的地方看起来不太实际。

    虐待导致马修的答案一个expression式的解决scheme:

     >>> x = {'a':1, 'b': 2} >>> y = {'b':10, 'c': 11} >>> z = (lambda f=x.copy(): (f.update(y), f)[1])() >>> z {'a': 1, 'c': 11, 'b': 10} 

    你说你想要一个expression式,所以我滥用lambda来绑定一个名称,而元组来覆盖lambda的一个expression式的限制。 随意嘲笑。

    你当然也可以这样做,如果你不在乎复制:

     >>> x = {'a':1, 'b': 2} >>> y = {'b':10, 'c': 11} >>> z = (x.update(y), x)[1] >>> z {'a': 1, 'b': 10, 'c': 11} 

    pythonic。 使用理解 :

     z={i:d[i] for d in [x,y] for i in d} >>> print z {'a': 1, 'c': 11, 'b': 10} 

    简单的解决scheme使用itertools保留顺序(后面的字典有优先权)

     import itertools as it merge = lambda *args: dict(it.chain.from_iterable(it.imap(dict.iteritems, args))) 

    这是用法:

     >>> x = {'a':1, 'b': 2} >>> y = {'b':10, 'c': 11} >>> merge(x, y) {'a': 1, 'b': 10, 'c': 11} >>> z = {'c': 3, 'd': 4} >>> merge(x, y, z) {'a': 1, 'b': 10, 'c': 3, 'd': 4} 

    即使这个浅层字典的答案是好的,但是这里定义的方法都没有深入的字典合并。

    示例如下:

     a = { 'one': { 'depth_2': True }, 'two': True } b = { 'one': { 'extra': False } } print dict(a.items() + b.items()) 

    人们会期待这样的结果:

     { 'one': { 'extra': False', 'depth_2': True }, 'two': True } 

    相反,我们得到这个:

     {'two': True, 'one': {'extra': False}} 

    如果它真的是合并,那么'one'条目应该在其字典中具有'depth_2'和'extra'作为项目。

    使用链也不起作用:

     from itertools import chain print dict(chain(a.iteritems(), b.iteritems())) 

    结果是:

     {'two': True, 'one': {'extra': False}} 

    rcwesick给的深度合并也创造了同样的结果。

    是的,它会合并样本字典,但没有一个是通用的合并机制。 稍后我会写一个真正的合并的方法。

    两本字典

     def union2(dict1, dict2): return dict(list(dict1.items()) + list(dict2.items())) 

    n词典

     def union(*dicts): return dict(itertools.chain.from_iterable(dct.items() for dct in dicts)) 

    sum有不好的performance。 请参阅https://mathieularose.com/how-not-to-flatten-a-list-of-lists-in-python/

     >>> x = {'a':1, 'b': 2} >>> y = {'b':10, 'c': 11} >>> x, z = dict(x), x.update(y) or x >>> x {'a': 1, 'b': 2} >>> y {'c': 11, 'b': 10} >>> z {'a': 1, 'c': 11, 'b': 10} 

    借鉴这里和其他地方的想法,我已经理解了一个function:

     def merge(*dicts, **kv): return { k:v for d in list(dicts) + [kv] for k,v in d.items() } 

    用法(在Python 3中testing):

     assert (merge({1:11,'a':'aaa'},{1:99, 'b':'bbb'},foo='bar')==\ {1: 99, 'foo': 'bar', 'b': 'bbb', 'a': 'aaa'}) assert (merge(foo='bar')=={'foo': 'bar'}) assert (merge({1:11},{1:99},foo='bar',baz='quux')==\ {1: 99, 'foo': 'bar', 'baz':'quux'}) assert (merge({1:11},{1:99})=={1: 99}) 

    你可以用lambda代替。

    至今列出的解决scheme的问题是,在合并的字典中,键“b”的值是10,但对于我的思维方式,它应该是12.有鉴于此,我提出如下:

     import timeit n=100000 su = """ x = {'a':1, 'b': 2} y = {'b':10, 'c': 11} """ def timeMerge(f,su,niter): print "{:4f} sec for: {:30s}".format(timeit.Timer(f,setup=su).timeit(n),f) timeMerge("dict(x, **y)",su,n) timeMerge("x.update(y)",su,n) timeMerge("dict(x.items() + y.items())",su,n) timeMerge("for k in y.keys(): x[k] = k in x and x[k]+y[k] or y[k] ",su,n) #confirm for loop adds b entries together x = {'a':1, 'b': 2} y = {'b':10, 'c': 11} for k in y.keys(): x[k] = k in x and x[k]+y[k] or y[k] print "confirm b elements are added:",x 

    结果:

     0.049465 sec for: dict(x, **y) 0.033729 sec for: x.update(y) 0.150380 sec for: dict(x.items() + y.items()) 0.083120 sec for: for k in y.keys(): x[k] = k in x and x[k]+y[k] or y[k] confirm b elements are added: {'a': 1, 'c': 11, 'b': 12} 

    对于Python 2:

     x = {'a':1, 'b': 2} y = {'b':10, 'c': 11} z = dict(x.items()+y.items()) print(z) 

    对于Python 3:

     x = {'a':1, 'b': 2} y = {'b':10, 'c': 11} z = dict(x.items()|y.items()) print(z) 

    它给出输出: {'a': 1, 'c': 11, 'b': 10}

    你可以使用toolz.merge([x, y])

    在python 3中:

     import collections a = {1: 1, 2: 2} b = {2: 3, 3: 4} c = {3: 5} r = dict(collections.ChainMap(a, b, c)) print(r) 

    date:

     {1: 1, 2: 2, 3: 4} 

    文档: https : //docs.python.org/3/library/collections.html#collections.ChainMap :

    使用字典理解,你可以

     x = {'a':1, 'b': 2} y = {'b':10, 'c': 11} dc = {xi:(x[xi] if xi not in list(y.keys()) else y[xi]) for xi in list(x.keys())+(list(y.keys()))} 

     >>> dc {'a': 1, 'c': 11, 'b': 10} 

    注意理解的if else语法

     { (some_key if condition else default_key):(something_if_true if condition else something_if_false) for key, value in dict_.items() } 

    这可以用一个单一的词典理解完成:

     >>> x = {'a':1, 'b': 2} >>> y = {'b':10, 'c': 11} >>> { key: y[key] if key in y else x[key] for key in set(x) + set(y) } 

    在我看来,“单一expression”部分的最佳答案是不需要额外的function,而且很短。

     from collections import Counter dict1 = {'a':1, 'b': 2} dict2 = {'b':10, 'c': 11} result = dict(Counter(dict1) + Counter(dict2)) 

    这应该可以解决你的问题。