파이썬에서 빈 목록 사전을 어떻게 초기화합니까?


88

프로그래밍 방식으로 목록 사전을 만들려는 시도는 사전 키를 개별적으로 처리 할 수 ​​없습니다. 목록 사전을 만들고 하나의 키에 추가하려고 할 때마다 모두 업데이트됩니다. 다음은 매우 간단한 테스트 케이스입니다.

data = {}
data = data.fromkeys(range(2),[])
data[1].append('hello')
print data

실제 결과: {0: ['hello'], 1: ['hello']}

예상 결과: {0: [], 1: ['hello']}

작동하는 것은 다음과 같습니다.

data = {0:[],1:[]}
data[1].append('hello')
print data

실제 및 예상 결과 : {0: [], 1: ['hello']}

fromkeys방법이 예상대로 작동하지 않는 이유는 무엇 입니까?

답변:


111

[]두 번째 인수로 전달 dict.fromkeys()하면 다소 쓸모없는 결과가 나타납니다. 사전의 모든 값은 동일한 목록 객체가됩니다.

Python 2.7 이상에서는 대신 사전 이해를 사용할 수 있습니다.

data = {k: [] for k in range(2)}

이전 버전의 Python에서는 다음을 사용할 수 있습니다.

data = dict((k, []) for k in range(2))

3
글쎄, 이것은 다소 직관적이지 않은 행동입니다. 왜 모든 키에 동일한 객체가 사용되는지에 대한 아이디어가 있습니까?
— Bar

3
@Bar Python 언어의 의미 체계 내에서 함수가 수행 할 수있는 다른 작업이 없기 때문입니다. 모든 키의 값으로 사용할 단일 객체를 전달하여 모든 키에 단일 객체가 사용되도록합니다. fromkeys()메서드가 팩토리 함수를 대신 받아들이 는 것이 더 좋을 것이므로 list함수로 전달할 수 있으며 해당 함수는 생성 된 각 키에 대해 한 번 호출되지만 실제 API는 아닙니다 dict.fromkeys().
— Sven Marnach

3
이것은 전혀 직관적이지 않습니다. 찾는 데 한 시간이 걸렸습니다. 감사합니다
— 아스트리드

1
dict ()를 두 번째 인수로 전달하는 경우에도 마찬가지입니다. 매우 당혹스러운 행동.
— 오를리

@Orly 이것은 처음에 하나의 빈 딕셔너리가 생성되고 그에 대한 참조가 모든 초기화에 전달되기 때문입니다.
— Dr_Zaszuś

83

대신 defaultdict 를 사용하십시오 .

from collections import defaultdict
data = defaultdict(list)
data[1].append('hello')

이렇게하면 목록에 사용하려는 모든 키를 미리 초기화 할 필요가 없습니다.

귀하의 예에서 일어나는 일은 하나의 (변경 가능한) 목록 을 사용한다는 것입니다 .

alist = [1]
data = dict.fromkeys(range(2), alist)
alist.append(2)
print data

출력 {0: [1, 2], 1: [1, 2]}합니다.


2
제 경우에는 나머지 프로그램 논리가 예상대로 작동 할 수 있도록 모든 키를 미리 초기화해야하지만 그렇지 않으면 좋은 해결책이 될 것입니다. 감사.
— Martin Burch 2012

나는이 답변에서 누락 된 것은이 솔루션이 OP와 달리 작동한다는 것입니다. 왜냐하면 list여기에는 빈 목록이 아니라 유형 이기 때문 입니다 (또는 호출 가능한 생성자로 볼 수 있습니다). 따라서 누락 된 키가 전달 될 때마다 동일한 키를 재사용하는 대신 새 목록이 생성됩니다.
— Dr_Zaszuś

8

단일 목록에 대한 참조로 사전을 채우므로 업데이트 할 때 업데이트가 모든 참조에 반영됩니다. 대신 사전 이해를 시도하십시오. Python에서 목록 이해력을 사용하여 사전 만들기를 참조 하십시오.

d = {k : v for k in blah blah blah}

사전 값 초기화에 대한 훌륭한 제안 ... 코비 감사합니다! 기존 사전의 값을 재설정하기 위해 예제를 확장했습니다. d. 나는 이것을 다음과 같이 수행했다 : d = {k : 0 for k in d}
— John

v이 대답 은 무엇입니까 ?
— Dr_Zaszuś

-2

이것을 사용할 수 있습니다.

data[:1] = ['hello']

2
이것이 작동 하는 이유 를 설명하는 것이 OP에 도움이 될 수 있습니다 . 원래 질문은 예상대로 작동하지 않는 이유를 알려줍니다.
— william.taylor.09

@ william.taylor.09 이것이 왜 작동하는지 분명하지 않습니까?
— Conner Dassen

OP는 "왜 fromkeys 메소드가 예상대로 작동하지 않습니까?"라고 묻습니다.
— william.taylor.09
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.