Home » 레퍼런스 » PYTHON » python defaultdict 콜렉션을 알아봅시다.

python defaultdict 콜렉션을 알아봅시다.

python defaultdict 클래스는 dict와 거의 비슷합니다. 다른 것은 키가 없을 때 default_factory로 값을 설정할 수 있다는 것입니다. 저는 이를 어떤 용도로 주로 쓰는가? 딕셔너리의 딕셔너리를 선언할 때? [] 연산에서 키가 없는 경우 처리를 하기 위해 자주 씁니다. 제가 출제한 이 문제에서도 이용할 수 있으니 이번 기회에 알아가도록 합시다.


dictionary의 getitem 함수

우리가 파이썬에서 딕셔너리를 언제 이용하나요? key를 빠르게 찾을 때 이용해요. 예를 들어 아래의 코드가 있다고 해 봅시다.

[그림 1] 1번 프로그램

2번째 줄에 dic[1]을 호출했어요. key 1에 대응되는 값을 얻어온다는 의미에요. 이 코드를 호출하면 함수 __getitem__ 이 호출됩니다. [] 을 호출했을 때, __getitem__이 호출됩니다.

[그림 2] 1번 프로그램의 결과

그런데, 만약에 dic[2]를 호출하면 어떻게 될까요?

[그림 3] dic[2]를 호출했을 때 결과

KeyError가 뜹니다. 이는 키가 없기 때문입니다. 여기까지 __getitem__ 함수의 흐름을 정리해 보겠습니다. 이 함수는 2가지 케이스로 나누어 집니다.

  • key가 있을 때
  • key가 없을 때

key가 있다면, 대응되는 값을 얻어옵니다. 그렇지 않으면 missing key이기 때문에 에러를 리턴합니다.

이 흐름이 대강이라도 이해되셨다면 다음으로 넘어갑시다.


python defaultdict 클래스와 __missing__

이제, __missing__ 으로 넘어가 보겠습니다. 이 함수는 __getitem__ 에서만 호출된다문서에 나와 있습니다. 이 말인 즉슨, get 함수를 호출해도, __missing__ 함수가 호출되지 않는다는 것입니다. python defaultdict 클래스 get 함수를 호출했을 때와, __getitem__을 호출했을 때 순서도를 그려 보도록 하겠습니다.

먼저 get 함수를 호출했을 때 순서도입니다. 키가 없는 경우, 그냥 missing key 이벤트만 발생합니다. 평소처럼 None을 리턴합니다. 왜? __getitem__ 에서만 함수 __missing__이 호출되기 때문입니다. 반면, __getitem(self, key)는 어떨까요?

그러면 __missing__(key)가 걸리면 어떻게 되는 건지 봐야 합니다. 이 때에는 다음과 같은 일이 일어납니다.

  • default_factory를 호출합니다.
    • 키가 없을 때 default 값을 생성해서 돌려줍니다.
  • 이 값을 value 라고 했을 때, key에 대응되는 값은 value라는 정보를 넣습니다.

무슨 이야기인지 예제 프로그램을 보면서 이야기 해 봅시다.

[그림 4] 2번 프로그램의 factory 함수

factory 함수는 위와 같아요. “factory” 라는 문구를 출력하고 새로운 리스트를 돌려줍니다.

[그림 5] 2번 프로그램의 본체

본체를 봅시다. defaultdict 생성자에 factory를 넣었어요. 이는, default 값을 생성하는 factory로 함수 factory를 넣는다는 의미입니다. 그냥 새로운 리스트 생성입니다. 다음 10번째 줄에 de[1].append(3)이 들어갔군요.

빈 defaultdict에는 키 1이 있을 리가 없으니, __missing__ 이 호출됩니다. 여기서 factory를 부르는데요. 제가 넘겨준 것은 빈 리스트였어요. 따라서, 키 1에 대응되는 값은 빈 리스트라는 정보가 딕셔너리에 추가됩니다.

다음에 append(3)이 실행됩니다. 그러면, 1에 대응되는 값인 빈 리스트에 3이 추가될 겁니다.

여기까지 상황이 이해 가시나요? 다음에 var = de[2]가 수행되고 나면, 아래와 같이 변할 겁니다.

de[2]를 호출했기 때문에 key 2에 대응되는 값은 빈 리스트라는 정보가 추가된 것입니다. 프로그램의 실행 결과를 볼까요?

[그림 6] 2번 프로그램의 수행 결과

factory가 2번 출력 되었습니다. 그리고 1에 대응되는 값은 [3], 2에 대응되는 값은 빈 리스트임을 알 수 있습니다. 이제, default factory의 역할을 다시 정리해 봅시다.

  • 사용자가 dic[k]를 호출합니다.
  • default dictionary에 키 값이 k인 것이 없었다면
    • default factory로 값 v를 만듭니다.
    • 키 k에 대응되는 값은 v라는 정보를 dic에 추가합니다.

결국 키 key가 없을 때, key에 대응되는 값이 디폴트 값이라는 정보를 넣기 위해, 디폴트 값을 생성해 주는 것이 default factory의 역할이라 할 수 있겠습니다.


또 다른 예제

그러면, 아래는 무엇을 의미할까요?

[그림 7] 3번 프로그램

default factory로 dict가 들어갔어요. 이 말은 무슨 이야기인가? 5번째 줄에서 de[1][3] = 1 문장이 있어요.

  • de[1] 에서 __getitem__(self, 1)을 호출해요.
  • 1이 없다면 default factory를 호출하는데 이게 마침 dict네요.
    • 키가 없으면 딕셔너리를 만든다는 의미입니다. 이를 v라 합시다.
    • 키 1에 대응되는 값은 v라는 정보를 de에 넣어요.

여기까지 수행해 봅시다. 그러면, 아래 그림과 같이 됩니다.

이제 de[1][3] = 1을 해석해 봅시다. de[1]에 대응되는 것은 그냥 딕셔너리에요. 이 딕셔너리에, key값이 3이고 value가 1이라는 정보를 넣어요. 그러면 어떻게 될까요?

요래 그려지게 됩니다. 즉, defaultdict 안에 dictionary가 들어가게 된 셈입니다. 이 구조를 잘 이용하면 제가 출제한 문제를 풀 수 있습니다.

Leave a Comment

6 + 2 =