9

병합, 우리는DICT 파이썬 3.5 DICT 이해

>>> d1 = {1: 'one', 2: 'two'} 
>>> d2 = {3: 'three'} 
>>> {**d1, **d2} 
{1: 'one', 2: 'two', 3: 'three'} 

쿨 풀고 더블 플랫을 사용하여 dicts을 병합 할 수 있습니다. 그래도, 동적 사용 사례를 일반화하지 않는 것 :

>>> ds = [d1, d2] 
>>> {**d for d in ds} 
SyntaxError: dict unpacking cannot be used in dict comprehension 

는 대신에 우리는 많은 추악한 것 reduce(lambda x,y: {**x, **y}, ds, {})을 수행해야합니다. 그 표현식에 애매한 점이없는 것처럼 파서가 "한 가지 확실한 방법"을 허용하지 않는 이유는 무엇입니까?

+1

다른 * 또는 ** - 압축 풀기 컨텍스트에서는이를 수행 할 수 없습니다. 즉, some_function (list_lists에서 x에 대해 * x)을 수행 할 수 없습니다. 언 패킹 별은 실제 연산자가 아니며 표현식에서 나타날 수 없습니다. – BrenBarn

+2

''{k : v에 대한 [d1, d2]의 d에 대한 v, d.items()}의 v '는''('')의 대안이 될 것입니다. –

+2

또 다른 대안은 개인적으로 마음에 들지 않는'dict (ChainMap (d2, d1))'입니다. 왜냐하면'ChainMap '이 어쨌든 누구를 알고 있기 때문입니까? –

답변

6

그것의 정확히 당신이 (병합 사전 - 라인) 제안 일을 할 수있는 관용적하고 우아한 방법이 ChainMap을 사용하는 것이 좋습니다 것입니다 귀하의 질문하지만에 대한 답변 : 그것은하지 비록

>>> d1 = {1: 'one', 2: 'two'} 
>>> d2 = {3: 'three'} 
>>> ds = [d1, d2] 
>>> dict(ChainMap(*ds)) 
{1: 'one', 2: 'two', 3: 'three'} 

을 특히 투명한 솔루션은 많은 프로그래머가 정확히 의 작동 방식을 모르기 때문에 가능합니다. "@AnttiHaapala가 지적한대로" "처음 찾은 것이 사용됨". 따라서 dictChainMap으로 보내기 전에 reversed으로 전화해야 할 수도 있습니다.

>>> d2 = {3: 'three', 2:'LOL'} 
>>> dict(ChainMap(*ds)) 
{1: 'one', 2: 'two', 3: 'three'} 

>>> dict(ChainMap(*reversed(ds))) 
{1: 'one', 2: 'LOL', 3: 'three'} 
3

나를 위해, 확실한 방법은 다음과 같습니다

d_out = {} 
for d in ds: 
    d_out.update(d) 

이 빠르고 아마 아주 성능이 좋은 것입니다. 나는 파이썬 개발자를 위해 말할 수 있는지 모르지만 예상 버전이 더 읽기 쉽다는 것을 모른다. 예를 들어, 당신의 이해력은 :의 부재로 인해 나에게 이해가 된 것처럼 보입니다. FWIW, 기술 이유 (예 : 파서 ​​모호성)가 있다고 생각하지 않습니다. 해당 이해할 수있는 형식을 추가 할 수 없습니다.

외관상으로는, these forms were proposed, 그러나 그들을 실행하기 위하여 보편적 인 충분한 지원이없는 (아직).

+0

명령문 대신 표현식을 사용하면 기능 스타일에 대해 가능한 유스 케이스가 증가합니다. for 루프가 항상 더 나은 경우 합병 식을 전혀 추가 할 이유가 없습니다. 제 질문은 의도적으로 알려진 피연산자 수로 의도적으로 제한된 이유에 대한 것입니다. – wim

+0

@wim - 기능적 접근 방식으로이 작업을 수행하려면이 함수를 다음과 같이 포장하십시오. 관련 PEP에서 논의 된 바와 같이, 의도적으로 제한된 이유는 커뮤니티에서 사용할 구문에 대한 충분한 합의가 없었기 때문입니다.아마도 그것은 미래에 언젠가 재검토 될 것이지만, 지금은 생략되어 모든 사람이 동의 한 부분이 구현 될 예정입니다. – mgilson