파이썬에서 두 개의 사전을 단일 표현식으로 병합하는 방법은 무엇입니까?


4782

나는 두 개의 파이썬 사전을 가지고 있으며이 두 사전을 반환하는 단일 표현식을 병합하려고합니다. 이 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()내가 찾고있는 것입니다.)


파이썬 3.9 알파를 사용하고있을 가능성이있는 경우, 다음을 사용하십시오.z = x | y
Daleks

답변:


5690

두 개의 파이썬 사전을 단일 표현식으로 병합하려면 어떻게해야합니까?

사전의 경우 xy, z얕게로부터 값을 사전에 합병되고 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)
  • 파이썬 3.9.0a4 이상 (최종 릴리스 날짜 2020 약 10월)에서 : PEP-584 , 여기서 논의 , 더이 문제를 단순화하기 위해 구현되었다 :

    z = x | y          # NOTE: 3.9+ ONLY

설명

두 개의 dicts가 있고 원래 dicts를 변경하지 않고 새 dict로 병합하려고한다고 가정하십시오.

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

원하는 결과는 z값이 병합 된 새 사전 ( ) 을 가져 오고 두 번째 dict의 값은 첫 번째 값을 덮어 씁니다.

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

제안이에 대한 새로운 구문, PEP (448)파이썬 3.5로 사용할 수는 있다

z = {**x, **y}

그리고 그것은 실제로 하나의 표현입니다.

리터럴 표기법과 병합 할 수도 있습니다.

z = {**x, 'foo': 1, 'bar': 2, **y}

그리고 지금:

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

이제 3.5, PEP 478 릴리스 일정에 구현 된 것으로 표시되며 이제 Python 3.5 문서 의 새로운 기능 으로 전환되었습니다 .

그러나 많은 조직이 여전히 Python 2를 사용하고 있으므로 이전 버전과 호환되는 방식으로이 작업을 수행 할 수 있습니다. Python 2 및 Python 3.0-3.4에서 사용할 수있는 고전적인 Pythonic 방식은 2 단계 프로세스로이를 수행하는 것입니다.

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

두 가지 접근 방식 모두에서 두 y번째로 올 것이며 그 값이의 값을 대체 할 x것이므로 최종 결과를 'b'가리킬 것 3입니다.

아직 Python 3.5에서는 없지만 단일 표현식을 원합니다.

아직 Python 3.5를 사용하지 않거나 이전 버전과 호환되는 코드를 작성해야하고 단일 표현식으로 작성 하려는 경우 가장 효과적인 방법은 코드를 함수에 넣는 것입니다.

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

그리고 하나의 표현이 있습니다.

z = merge_two_dicts(x, y)

정의되지 않은 수의 dict을 0에서 매우 큰 수로 병합하는 함수를 만들 수도 있습니다.

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

이 함수는 모든 dicts에 대해 Python 2 및 3에서 작동합니다. 예를 들면 다음 ag같습니다.

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

과에서 키 값 쌍은 gdicts보다 우선합니다 af, 등등.

다른 답변의 비판

이전에 받아 들여진 답변에 표시된 것을 사용하지 마십시오.

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

Python 2에서는 각 dict에 대해 메모리에 두 개의 목록을 작성하고 처음 두 개의 길이와 같은 길이의 메모리에 세 번째 목록을 작성한 다음 세 목록을 모두 버리고 dict를 작성하십시오. Python 3에서는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'

예를 들어 목록으로 명시 적으로 작성해야합니다 z = dict(list(x.items()) + list(y.items())). 이것은 자원과 계산 능력의 낭비입니다.

마찬가지로, items()파이썬 3에서 ( viewitems()파이썬 2.7에서) 통합을 취하는 것도 값이 해시 불가능한 객체 (예 : 목록) 일 때 실패합니다. 값이 해시 가능하더라도 집합은 의미 적으로 순서가 지정되지 않으므로 우선 순위와 관련하여 동작이 정의되지 않습니다. 따라서 이것을하지 마십시오 :

>>> 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생성자를 사용하며 매우 빠르고 메모리 효율적입니다 (우리의 2 단계 프로세스보다 약간 더 많음). 여기서 무슨 일이 일어나고 있는지 정확히 알지 못하면 (즉, 두 번째 dict는 dict에 키워드 인수로 전달됩니다. 생성자), 읽기가 어렵고 의도 된 사용법이 아니기 때문에 Pythonic이 아닙니다.

다음 은 django에서 사용되는 사용법의 예입니다 .

딕셔너리는 해시 가능 키 (예 : 고정 세트 또는 튜플)를 사용하려고하지만 키가 문자열이 아닌 경우 Python 3에서이 방법이 실패합니다.

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

로부터 메일 링리스트 , 귀도 반 로섬 (Guido van Rossum), 언어의 창조자는 썼다 :

나는 dict ({}, ** {1 : 3})을 불법으로 선언하는 것이 좋습니다. 결국 ** 메커니즘을 남용하기 때문입니다.

분명히 dict (x, ** y)는 "call x.update (y) and return x"에 대한 "cool hack"으로 돌아가고 있습니다. 개인적으로 나는 그것이 차가운 것보다 더 비열한 것을 안다.

의도 된 사용법 은 가독성을위한 사전 작성을 위한 것임을 이해하는 것입니다 ( 예 : 언어 작성자의 이해 ) dict(**y).

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

대신에

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

의견에 대한 답변

Guido의 말에도 불구하고 dict(x, **y)dict 사양과 일치합니다. 이것은 파이썬 2와 3 모두에서 작동합니다. 이것은 문자열 키에서만 작동한다는 사실은 키워드 매개 변수가 작동하는 방식의 직접적인 결과이며 dict의 단점이 아닙니다. ** 대신에 ** 연산자를 사용하여 메커니즘을 남용하지 않습니다. 실제로 **는 dicts를 키워드로 전달하도록 정확하게 설계되었습니다.

키가 문자열이 아닌 경우에도 3에서 작동하지 않습니다. 암시 적 호출 계약은 네임 스페이스가 일반적인 dicts를 취하는 반면 사용자는 문자열 인 키워드 인수 만 전달해야한다는 것입니다. 다른 모든 소명은 그것을 시행했다. dict파이썬 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}

파이썬 (Pypy, Jython, IronPython)의 다른 구현을 고려할 때이 불일치가 나빴습니다. 따라서이 사용법은 주요 변경 사항이 될 수 있으므로 Python 3에서 수정되었습니다.

한 버전의 언어에서만 작동하거나 특정 임의의 제약 조건에서만 작동하는 코드를 의도적으로 작성하는 것은 악의적 인 무능함이라고 귀하에게 제출합니다.

더 많은 의견 :

dict(x.items() + y.items()) 여전히 파이썬 2에서 가장 읽기 쉬운 솔루션입니다.

내 대답 : merge_two_dicts(x, y)실제로 가독성에 관심이 있다면 실제로 나에게 훨씬 분명해 보입니다. 그리고 파이썬 2가 점점 더 이상 사용되지 않으므로 앞으로 호환되지 않습니다.

{**x, **y}중첩 된 사전을 처리하지 않는 것 같습니다. 중첩 된 키의 내용은 단순히 덮어 쓰지 않고 병합되지 않습니다. [...] 나는 재귀 적으로 병합되지 않는 이러한 답변에 의해 화상을 입었고 아무도 그것을 언급하지 않은 것에 놀랐습니다. "병합"이라는 단어를 해석 할 때이 답변은 "한 dict을 다른 dict로 업데이트"하고 병합하지 않는 것을 설명합니다.

예. 나는 두 개의 사전을 얕게 병합 하고 첫 번째 값 을 번째 값으로 덮어 씁니다.

두 개의 사전 사전을 가정하면 하나를 재귀 적으로 단일 함수로 병합 할 수 있지만 소스 중 하나에서 dicts를 수정하지 않도록주의해야하며 값을 지정할 때 사본을 작성하지 않아야합니다. 키는 해시 가능해야하며 일반적으로 불변이므로 키를 복사하는 것은 의미가 없습니다.

from copy import deepcopy

def dict_of_dicts_merge(x, y):
    z = {}
    overlapping_keys = x.keys() & y.keys()
    for key in overlapping_keys:
        z[key] = dict_of_dicts_merge(x[key], y[key])
    for key in x.keys() - overlapping_keys:
        z[key] = deepcopy(x[key])
    for key in y.keys() - overlapping_keys:
        z[key] = deepcopy(y[key])
    return z

용법:

>>> x = {'a':{1:{}}, 'b': {2:{}}}
>>> y = {'b':{10:{}}, 'c': {11:{}}}
>>> dict_of_dicts_merge(x, y)
{'b': {2: {}, 10: {}}, 'a': {1: {}}, 'c': {11: {}}}

다른 값 유형에 대한 우발적 인 문제는이 질문의 범위를 훨씬 넘어서므로 "사전의 사전 병합"에 대한 표준 질문에 대한 답변을 알려 드리겠습니다 .

성능은 떨어지지 만 Ad-hoc은 정확

이러한 접근 방식은 성능이 떨어지지 만 올바른 동작을 제공합니다. 그들은 것입니다 훨씬 성능이 좋은 이상 copyupdate새로운 풀기가 더 높은 추상화 수준에서 각 키 - 값 쌍을 반복하기 때문에 나,하지만 그들은 우선 순위를 (후자 dicts이 우선 순위가) 존중

dict 이해 내에서 dicts를 수동으로 연결할 수도 있습니다.

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

또는 파이썬 2.6 (및 생성기 표현식이 도입되었을 때 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

사전에 대한 자료


9
@MohammadAzim "strings only"는 일반 언 패킹 구문이 아닌 콜 러블의 키워드 인수 확장에만 적용됩니다. 이것이 효과가 있음을 증명하기 위해 : {**{(0, 1):2}}->{(0, 1): 2}
Aaron Hall

36
z = {**x, **y}실제로 나를 자극하는 것과 같은 짧은 답변
pcko1

1
PEP-0584가 승인되면 변경 될 수 있습니다. 새로운 조합 연산자는 다음 구문으로 구현됩니다.x | y
Callam Delaney

2
답변 상단에 요약이 필요한 경우 너무 깁니다.
Gringo Suave

2
안녕하세요, 상단은 요약입니다. 당신에게 달려 있습니다. 모든 것이 훌륭한 블로그 게시물이 될 것입니다. 참고 Py 3.4 이하는 2020-09의 EOL에 근접한 EOL, 3.5입니다.
Gringo Suave

1616

귀하의 경우 할 수있는 일은 다음과 같습니다.

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

이것은 원하는대로 최종 dict를 넣고 두 번째 dict z의 값으로 key의 값을 b올바르게 재정의 y합니다.

>>> 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을 사용하면 조금 더 복잡합니다. 만들려면 z:

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

Python 버전 3.9.0a4 이상을 사용하는 경우 직접 사용할 수 있습니다.

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

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

1
비효율적이므로 이것을 사용하지 마십시오. 래퍼 함수가 옵션이 아니었지만 해당 날짜가 지난 경우 Py2 일에 필요할 수 있습니다.
Gringo Suave

633

대안:

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

83
이것이 이것이 질문에 의해 제공된 기준을 충족시키지 못하는 이유를 명확히하기 위해 : 그것은 단일 표현이 아니며 z를 반환하지 않습니다.
Alex

2
@neuronet 모든 oneliner는 일반적으로 다른 구성 요소로 발생 해야하는 코드를 이동시켜 해결합니다. 이것은 분명히 사례 중 하나입니다. 그러나 다른 언어는 파이썬보다 더 좋은 구조를 가지고 있습니다. 요소를 반환하는 참조 가능한 투명 변형을 갖는 것이 좋습니다.
Alex

12
이런 식으로 말하면 : 한 줄의 코드를 설명하는 두 줄의 주석을 코드를 전달하는 사람들에게 줄 필요가 있다면 ... 한 줄로 실제로 했습니까? :) 나는 파이썬이 이것에 좋지 않다는 것에 완전히 동의합니다. 훨씬 쉬운 방법이 있어야합니다. 이 답변은 더 파이썬 적이지만 실제로는 명백하거나 명확합니까? Update사람들이 많이 사용하는 "핵심"기능 중 하나가 아닙니다.
eric

글쎄, 사람들이 그것을 하나의 라이너로 만들려고 고집한다면, 당신은 항상 할 수 있습니다 (lambda z: z.update(y) or z)(x.copy()): P
towr

340

또 다른 간결한 옵션 :

z = dict(x, **y)

참고 : 이것은 대중적인 대답이되었지만 y문자열이 아닌 키가있는 경우 이것이 작동한다는 사실은 CPython 구현 세부 사항을 남용하고 Python 3에서는 작동하지 않는다는 점을 지적하는 것이 중요합니다 . 또는 PyPy, IronPython 또는 Jython에서. 또한 Guido는 팬이 아닙니다 . 따라서 순방향 호환 또는 교차 구현 휴대용 코드에 대해서는이 기술을 권장 할 수 없습니다. 이는 완전히 피해야한다는 것을 의미합니다.


Python 3 및 PyPy 및 PyPy 3 에서 제대로 작동하며 Jython 또는 Iron과 대화 할 수 없습니다. 이 패턴을 명시 적으로 문서화 하면 (이 문서 의 세 번째 생성자 양식 참조) "구현 세부 사항"이 아니라 의도적 인 기능 사용이라고 주장합니다.
amcgregor

5
@amcgregor "y가 문자열이 아닌 키를 가지고 있다면"이라는 핵심 문구를 놓쳤습니다. 그것이 Python3에서 작동하지 않는 것입니다. CPython 2에서 작동한다는 사실은 신뢰할 수없는 구현 세부 사항입니다. IFF의 모든 키는 문자열로 보장되며 완전히 지원되는 옵션입니다.
칼 메이어

214

이것은 아마도 대중적인 대답은 아니지만 아마도 거의 그렇게하고 싶지 않습니다. 병합 된 사본을 원할 경우 copy (또는 원하는 내용에 따라 deepcopy )를 사용한 다음 업데이트하십시오. 두 줄의 코드는 .items () + .items ()로 한 줄을 만드는 것보다 훨씬 더 읽기 쉽습니다. 암시적인 것보다 명시적인 것이 좋습니다.

또한 .items () (Python 3.0 이전)를 사용하면 dict의 항목을 포함하는 새 목록을 만듭니다. 사전이 큰 경우 오버 헤드가 많이 발생합니다 (병합 된 dict가 작성되는 즉시 버려지는 두 개의 큰 목록). update ()는 항목별로 두 번째 dict을 실행할 수 있기 때문에 더 효율적으로 작동 할 수 있습니다.

시간 측면에서 :

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

IMO 첫 두 개 사이의 작은 속도 저하는 가독성을 위해 가치가 있습니다. 또한 사전 생성을위한 키워드 인수는 Python 2.3에서만 추가되었지만 copy () 및 update ()는 이전 버전에서 작동합니다.


150

후속 답변에서이 두 대안의 상대적 성능에 대해 물었습니다.

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

내 컴퓨터에서 (Python 2.5.2를 실행하는 상당히 일반적인 x86_64) 대안 z2은 짧고 간단 할뿐만 아니라 훨씬 빠릅니다. timeit파이썬과 함께 제공 되는 모듈을 사용하여 직접 확인할 수 있습니다 .

예 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

z23.5 배 정도 승리합니다. 다른 사전은 매우 다른 결과를 산출하는 것처럼 보이지만 z2항상 앞서 나오는 것처럼 보입니다. ( 동일한 테스트에 대해 일관되지 않은 결과가 나오면 -r기본값 3보다 큰 숫자로 전달 하십시오.)

예제 2 : 겹치지 않는 사전은 252 개의 짧은 문자열을 정수로 매핑하거나 그 반대로 매핑합니다.

% 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 내 책에서 꽤 큰 승리입니다!

이 두 가지를 비교 한 후의 z1성능 저하가 두 항목 목록 구성의 오버 헤드로 인한 것일 수 있는지 궁금해서이 변형이 더 잘 작동하는지 궁금해졌습니다.

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

몇 가지 빠른 테스트, 예 :

% 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

그것 z3보다 약간 빠르지 z1만 거의 빠르지 않다는 결론을 이끌어 z2냅니다. 여분의 타이핑을 모두 가치가 없습니다.

이 논의에는 여전히 중요한 것이 빠져 있는데, 이는 두 대안을 병합하는 "명확한"방법과 이러한 대안을 성능 비교하는 update것입니다. 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본질적으로 동일한 성능을 갖고있는 것 같다. 이것이 우연의 일치라고 생각하십니까? 난 ...

사실, 순수한 파이썬 코드가 이것보다 더 나은 것은 불가능하다고 주장하기까지하였습니다. 그리고 C 확장 모듈에서 훨씬 더 잘 할 수 있다면, 파이썬 사람들이 코드 (또는 접근 방식의 변형)를 파이썬 코어에 통합하는 데 관심이있을 것입니다. 파이썬은 dict많은 곳에서 사용 합니다; 운영 최적화는 큰 문제입니다.

이것을 다음과 같이 쓸 수도 있습니다.

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

Tony와는 달리 (놀랍지 않게) 표기법의 차이는 성능에 측정 가능한 영향을 미치지 않는 것으로 나타났습니다. 나에게 맞는 것을 사용하십시오. 물론, 그는 2 문장 버전이 이해하기 훨씬 쉽다는 것을 지적하는 것이 옳습니다.


5
파이썬 3에서는 작동하지 않습니다. items()적합 iteritems하지 않으며 존재하지 않습니다.
Antti Haapala

127

파이썬 3.0 이상에서 , 당신이 사용할 수있는 collections.ChainMap하나의 업데이트 할 수있는 뷰를 생성하기 위해 함께하는 그룹 여러 dicts 또는 다른 매핑을 :

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

a --> 1
b --> 10
c --> 11

Python 3.5 이상 업데이트 : PEP 448 확장 사전 패킹 및 언 패킹을 사용할 수 있습니다 . 이것은 빠르고 쉽습니다.

>>> x = {'a':1, 'b': 2}
>>> y = y = {'b':10, 'c': 11}
>>> {**x, **y}
{'a': 1, 'b': 10, 'c': 11}

3
그러나 ChainMap을 사용하는 동안주의해야합니다. 중복 키가있는 경우 첫 번째 매핑의 값이 사용되며 delon 을 호출 하면 ChainMap c가 해당 키의 첫 번째 매핑을 삭제한다는 캐치가 있습니다.
Slayer

7
@Prerit 다른 무엇을 기대하십니까? 이것이 체인 네임 스페이스가 작동하는 일반적인 방식입니다. bash에서 $ PATH가 어떻게 작동하는지 고려하십시오. 경로에서 실행 파일을 삭제해도 동일한 업스트림 이름을 가진 다른 실행 파일은 제외되지 않습니다.
Raymond Hettinger

2
@Raymond Hettinger 동의합니다. 방금주의를 기울였습니다. 대부분의 사람들은 그것에 대해 알지 못할 수 있습니다. : D
Slayer

@Prerit 당신은 dict그것을 피하기 위해 캐스팅 할 수 있습니다 , 즉 :dict(ChainMap({}, y, x))
wjandrea

113

비슷한 것을 원했지만 중복 키의 값을 병합하는 방법을 지정할 수있는 기능을 사용하여 해킹했습니다 (그러나 크게 테스트하지는 않았습니다). 분명히 이것은 단일 표현식이 아니라 단일 함수 호출입니다.

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

88

재귀 적 / 영향 업데이트

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

편집 해 주셔서 감사합니다.


1
이것은 질문에 대답하지 않습니다. 이 질문은 원래 사전 x 및 y에서 새로운 사전 z를 요구하며 y의 값은 업데이트 된 사전이 아닌 x의 값을 대체합니다. 이 답변은 x의 값을 추가하여 y를 제자리에서 수정합니다. 더 나쁜 것은 이러한 값을 복사하지 않으므로 수정 된 사전 y를 추가로 수정할 수 있으며 수정이 사전 x에 반영 될 수 있습니다. @ Jérôme이 코드로 인해 응용 프로그램에 버그가 발생하지 않기를 바랍니다. 적어도 딥 카피를 사용하여 값을 복사하는 것이 좋습니다.
Aaron Hall

1
@AaronHall은 이것이 질문에 대답하지 않는다는 데 동의했습니다. 그러나 그것은 나의 필요에 대답합니다. 나는 그 한계를 이해하지만 내 경우에는 문제가되지 않습니다. 그것을 생각하면 아마도 그 이름이 심오한 사본을 불러 일으킬 수 있기 때문에 오해의 소지가 있습니다. 그러나 깊은 중첩 문제를 해결합니다. 여기에 Martellibot에서 다른 구현이다 : stackoverflow.com/questions/3232943/... .
Jérôme

72

사본을 사용하지 않고 생각할 수있는 가장 좋은 버전은 다음과 같습니다.

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

적어도 CPython에서는 dict(x.items() + y.items())빠르지 만 빠르지는 않습니다 n = copy(a); n.update(b). 당신이 변경되면이 버전은 또한 파이썬 3 일 iteritems()items()자동으로 2to3 도구에 의해 수행된다.

개인적으로이 버전은 단일 기능 구문에서 원하는 것을 상당히 잘 설명하기 때문에 가장 좋습니다. 유일한 사소한 문제는 y의 값이 x의 값보다 우선한다는 것이 완전히 명백하지 않다는 것입니다. 그러나 나는 그것을 알아내는 것이 어렵다고 생각하지 않습니다.


71

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}

Python 3.9에서는 | 및 PEP 584의 아래 예와 함께 | =

d = {'spam': 1, 'eggs': 2, 'cheese': 3}
e = {'cheese': 'cheddar', 'aardvark': 'Ethel'}
d | e
# {'spam': 1, 'eggs': 2, 'cheese': 'cheddar', 'aardvark': 'Ethel'}

이 솔루션은 어떤 방법으로 dict(x, **y)-solution 보다 낫습니까? 귀도 (@CarlMeyer)가 귀하 자신의 답변 ( stackoverflow.com/a/39858/2798610 )에 언급 한대로 귀도는 해당 솔루션이 불법 이라고 간주합니다 .
Blackeagle52

14
Guido 는 유효한 키워드 인수 이름 인 키만 dict(x, **y)사용해야한다는 이유로 (매우 좋은) 싫어 합니다 ( ydict 생성자가 속이는 CPython 2.7을 사용하지 않는 한). 이 반대 / 제한은 PEP 448에는 적용되지 않으며, **리터럴을 지시하기 위한 압축 풀기 구문을 일반화합니다 . 따라서이 솔루션은 dict(x, **y)단점없이 동일한 결정을 갖습니다 .
Carl Meyer

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

두 사전에 모두 키가있는 항목 ( 'b')의 경우 마지막에 두어 출력에서 ​​어떤 키가 나오는지 제어 할 수 있습니다.


파이썬 3에서는 TypeError : + : 'dict_items'및 'dict_items'에 대해 지원되지 않는 피연산자 유형이 표시됩니다 ... dict (list (x.items ()) + list (y.items ()))
justSay

49

질문에 이미 여러 차례 답변되었지만 문제에 대한이 간단한 해결책은 아직 나열되지 않았습니다.

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

z0과 위에서 언급 한 악한 z2만큼 빠르지 만 이해하고 변경하기 쉽습니다.


3
그러나 그것은 하나의 표현이 아닌 세 가지 진술입니다
fortran

14
예! 언급 된 하나의 표현 솔루션은 느리거나 악하다. 좋은 코드는 읽고 유지 관리 할 수 ​​있습니다. 따라서 문제는 답이 아닌 문제입니다. 우리는 한 줄 해결책이 아닌 최상의 문제 해결책을 요구해야합니다.
phobie

7
코드를 잃어 버리고 z4 = {}다음 줄을 바꾸십시오. z4 = x.copy()좋은 코드만으로는 불필요한 작업을 수행하지 않는 것보다 낫습니다.
martineau

3
당신의 제안은 이것을 매튜스의 대답으로 바꿀 것입니다. 그의 대답은 훌륭하지만 내 것이 더 읽기 쉽고 유지 관리하기 쉽다고 생각합니다. 추가 라인은 실행 시간이 걸리는 경우에만 나빠질 수 있습니다.
phobie

47
def dict_merge(a, b):
  c = a.copy()
  c.update(b)
  return c

new = dict_merge(old, extras)

이러한 그늘지고 모호한 답변 중에서도이 빛나는 예는 독재자가 Guido van Rossum 생명의 독재자에 의해 승인 된 파이썬에서 받아쓰기를 통합하는 유일한 방법입니다 ! 다른 사람이 이것의 절반을 제안했지만 기능에 넣지 않았습니다.

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

제공합니다 :

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

39

람다가 악하다고 생각하면 더 이상 읽지 마십시오. 요청에 따라 하나의 식으로 빠르고 메모리 효율적인 솔루션을 작성할 수 있습니다.

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}

위에서 제안했듯이 두 줄을 사용하거나 함수를 작성하는 것이 더 좋은 방법 일 것입니다.


33

피 토닉이 되십시오. 이해력을 사용하십시오 :

z={i:d[i] for d in [x,y] for i in d}

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

1
기능으로 :def dictmerge(*args): return {i:d[i] for d in args for i in d}
jessexknight

1
키 / 값 쌍을 직접 반복하여 조회를 저장하십시오.z={k: v for d in (x, y) for k, v in d.items()}
ShadowRanger

30

python3에서 items메소드 는 더 이상 list 처럼 보이지 않고 오히려 view 처럼 리턴합니다 . 이 경우 연결 +이 작동하지 않으므로 집합 조합을 가져와야 합니다.

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

버전 2.7의 python3과 유사한 동작의 경우이 viewitems메소드는 items다음 대신 작동해야합니다 .

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

어쨌든이 표기법을 선호합니다. 제목이 보여주는 것처럼 연결이 아닌 정해진 조합 작업으로 생각하는 것이 더 자연 스럽기 때문입니다.

편집하다:

파이썬 3에 대한 몇 가지 사항이 있습니다. 첫째, dict(x, **y)키가 없으면 파이썬 3 에서는 트릭이 작동하지 않습니다.y 가 문자열이 .

또한 Raymond Hettinger의 Chainmap 답변 은 인수로 임의의 수의 dicts를 취할 수 있기 때문에 매우 우아 합니다 .

조회는 키를 찾을 때까지 기본 매핑을 연속적으로 검색합니다.

응용 프로그램에 많은 조회가있는 경우 속도가 느려질 수 있습니다.

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

따라서 조회 속도가 약 느려집니다. 나는 Chainmap의 팬이지만 많은 조회가있을 때 실용적이지 않습니다.


22

Matthew의 답변에 대한 단일 표현 솔루션으로 이어지는 학대 :

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

당신은 한 가지 표현을 원한다고 말 했어요 lambda 이름을 묶는 하고 튜플은 람다의 한 표현 제한을 무시합니다. 자유롭게 울부 짖습니다.

복사에 신경 쓰지 않으면 물론이 작업을 수행 할 수도 있습니다.

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

22

순서를 유지하는 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}


16

얕은 사전 에는 답이 좋았지 만 여기에 정의 된 방법 중 어느 것도 실제로 깊은 사전 병합을 수행하지 않습니다.

예는 다음과 같습니다.

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

'하나'항목은 사전에 병합 된 경우 사전에 항목으로 'depth_2'및 'extra'가 있어야합니다.

체인을 사용하면 작동하지 않습니다.

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

결과 :

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

rcwesick이 준 깊은 병합도 같은 결과를 만들어냅니다.

예, 샘플 사전을 병합하는 것이 좋지만 일반적인 병합 메커니즘은 없습니다. 진정한 병합을 수행하는 메서드를 작성하면 나중에 업데이트하겠습니다.


11

(Python2.7 * 만 해당; Python3 *에는 더 간단한 솔루션이 있습니다.)

표준 라이브러리 모듈을 가져 오지 않으려면 다음을 수행하십시오.

from functools import reduce

def merge_dicts(*dicts):
    return reduce(lambda a, d: a.update(d) or a, dicts, {})

(의 or a비트는 항상 성공으로 돌아 lambda오기 때문에 필요 dict.update합니다 None.)


11

당신이 돌연변이 괜찮다면 x,

x.update(y) or x

간단하고 읽기 쉬운 성능. 항상을 반환한다는 것을 알고 있습니다. 이는 잘못된 값입니다. 따라서 위 표현식은 업데이트 후 항상로 평가됩니다 .update()Nonex

표준 라이브러리의 뮤팅 메소드 (예 :) 는 규칙에 따라 .update()반환 되므로이 None패턴도 작동합니다. 이 규칙을 따르지 않는 방법을 사용하면 작동하지 않을 or수 있습니다. 그러나 튜플 디스플레이 및 인덱스를 사용하여 단일 표현식으로 만들 수 있습니다. 이것은 첫 번째 요소가 무엇을 평가하는지에 관계없이 작동합니다.

(x.update(y), x)[-1]

당신이없는 경우 x아직 변수에, 당신이 사용할 수있는 lambda할당 문을 사용하지 않고 지역을 만들기 위해. 이것은 기능 표현 언어에서 일반적인 기술이지만 비유 사적 인 let 식 으로 사용 lambda하는 것입니다.

(lambda x: x.update(y) or x)({'a': 1, 'b': 2})

새로운 walrus 연산자 (Python 3.8+ 만 해당)를 다음과 다르게 사용하는 것은 아닙니다.

(x := {'a': 1, 'b': 2}).update(y) or x

사본을 원하면 PEP 448 스타일이 가장 쉽습니다 {**x, **y}. 그러나 (이전의) Python 버전에서 사용할 수 없다면 let 패턴도 작동합니다.

(lambda z: z.update(y) or z)(x.copy())

(물론 이는 (z := x.copy()).update(y) or z파이썬 버전 과 동일 하지만 파이썬 버전이 충분히 새 버전이라면 PEP 448 스타일을 사용할 수 있습니다.)


10

여기 및 다른 곳에서 아이디어를 작성하여 기능을 이해했습니다.

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

사용법 (파이썬 3에서 테스트) :

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

대신 람다를 사용할 수 있습니다.


10

지금까지 솔루션에 대해 가지고있는 문제는 병합 된 사전에서 키 "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}

1
당신은에 관심이있을 수 있습니다 cytoolz.merge_with( toolz.readthedocs.io/en/latest/… )
bli

10

.update아무것도 반환하지 않는 것은 너무 바보입니다 .
간단한 도우미 함수를 사용하여 문제를 해결합니다.

def merge(dict1,*dicts):
    for dict2 in dicts:
        dict1.update(dict2)
    return dict1

예 :

merge(dict1,dict2)
merge(dict1,dict2,dict3)
merge(dict1,dict2,dict3,dict4)
merge({},dict1,dict2)  # this one returns a new copy

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

문제가 해결 될 것입니다.


9

단일 dict 이해력으로 수행 할 수 있습니다.

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

필자의 견해로는 추가 함수가 필요하지 않으므로 '단일 표현'부분에 대한 가장 좋은 대답은 짧습니다.


그래도 성능은 그리 좋지 않을 것입니다. 각 dict에서 집합을 만든 다음 키를 반복하는 것만으로 매번 값을 다시 검색 할 수 있습니다 (상대적으로 빠르지 만 여전히 스케일링 기능의 순서가 증가 함)
Breezer

2
그것은 모두 우리가 사용하는 파이썬 버전에 달려 있습니다. 3.5 이상에서 {** x, ** y}는 연결된 사전을 제공합니다
Rashid Mv

9

PEP 572 : Assignment Expressions 덕분에 Python 3.8 릴리스 ( 2019 년 10 월 20 일 예정 )에 새로운 옵션이 제공됩니다 . 새로운 대입 표현식 연산자를 사용하면의 결과를 할당 하고 여전히 호출에 사용 하여 결합 된 코드를 두 개의 문이 아닌 단일 식으로 유지하면서 다음을 변경할 수 있습니다.:=copyupdate

newdict = dict1.copy()
newdict.update(dict2)

에:

(newdict := dict1.copy()).update(dict2)

모든면에서 동일하게 행동합니다. 결과를 반환 해야하는 경우 dict( dict위 의 ;을 반환하는 표현식을 요청 newdict했지만 위의을 만들고 할당 하지만 반환하지 않으므로 인수를 그대로 함수에 전달하는 데 사용할 수 없습니다 : la myfunc((newdict := dict1.copy()).update(dict2))) 그런 다음 or newdict끝에 추가 하십시오 ( updatereturns None이므로 거짓이므로 newdict표현식의 결과로 평가되어 반환 됩니다).

(newdict := dict1.copy()).update(dict2) or newdict

중요한 경고 : 일반적으로이 접근 방식을 권장하지 않습니다.

newdict = {**dict1, **dict2}

포장 풀기 접근 방식 (일반, 처음에 포장을 풀고 알고있는 사람에게 명확 있는 당신이해야 즉시에 전달되는 임시을 구성 할 때 훨씬 더 간결은 그래서 (모두에서 결과의 이름을 필요로하지 않습니다) 함수 또는 list/ tuple리터럴 등에 포함 )하고 거의 확실히 더 빠르며 (CPython에서) 대략 다음과 같습니다.

newdict = {}
newdict.update(dict1)
newdict.update(dict2)

그러나 구체적인 dictAPI를 사용하여 C 레이어에서 수행 되므로 동적 메소드 조회 / 바인딩 또는 함수 호출 디스패치 오버 헤드가 발생하지 않습니다 (여기서(newdict := dict1.copy()).update(dict2) 동적 검색하여, 별도의 단계에서 작업을 수행하는 동작 원래 두 라이너 불가피 동일 / 바인딩 / 메소드 호출

dicts 를 병합하는 것이 분명하기 때문에 확장 성 이 뛰어납니다.

 newdict = {**dict1, **dict2, **dict3}

할당 표현식을 사용하면 그렇게 확장되지 않습니다. 당신이 얻을 수있는 가장 가까운 것은 :

 (newdict := dict1.copy()).update(dict2), newdict.update(dict3)

또는 일시적인 튜플이 None없지만 각 None결과에 대한 진실성 테스트는 다음과 같습니다 .

 (newdict := dict1.copy()).update(dict2) or newdict.update(dict3)

이들 중 어느 하나 분명히 훨씬 더 추한이고, 상기 비 효율성을 포함하는 (하나 낭비 임시 tupleNone콤마 분리 또는 각각의 무의미한 truthiness 테스트에 대한 S updateNone답례 or분리).

다음과 같은 경우 대입 식 접근 방식의 유일한 장점은 다음과 같습니다.

  1. sets와 dicts를 모두 처리 해야하는 일반 코드가 있습니다 (둘 다 지원 copyupdate이므로 코드는 예상대로 작동합니다)
  2. 당신dict그 자체 만이 아니라 임의의 dict-like objects를받을 것으로 예상하고 (plain로 끝나지 않고) 왼쪽의 유형과 의미를 보존해야합니다dict . myspecialdict({**speciala, **specialb})작동 할 수도 있지만 여분의 임시 작업이 필요할 수 있으며 일반 기능을 유지할 수없는 기능이있는 dict경우 (예 : 일반 s는 이제 첫 번째 키 모양을 기준으로 순서를 유지하고 키의 마지막 모양을 기반으로 값을 유지합니다. 마지막 에 따라 순서를 유지하는 것myspecialdictdictdict 키 모양 하므로 값을 업데이트하면 값이 끝으로 이동합니다.) 의미가 잘못되었습니다. 대입 표현식 버전은 명명 된 메소드를 사용하므로 (적절하게 작동하도록 오버로드 될 수 있음)dict전혀 ( dict1아직이 아닌 한 dict), 모든 임시 유형을 피하면서 원래 유형 (및 원래 유형의 의미)을 유지하십시오.

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

이 메소드 x는 사본으로 겹쳐 씁니다 . x함수 인수 인 경우 작동하지 않습니다 ( 참조 )
bartolo-otrit
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.