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


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.