본문 바로가기
Engineering WIKI/Python

유사 딕셔너리 defaultdict() 활용법

by wonos 2022. 5. 19.

defaultdict()는 딕셔너리를 만드는 dict클래스의 서브클래스이다.

작동하는 방식은 거의 동일한데, defaultdict()는 인자로 주어진 객체(default-factory)의 기본값을 딕셔너리값의 초깃값으로 지정할 수 있다.

숫자, 리스트, 셋등으로 초기화 할 수 있기때문에 여러 용도로 사용할 수 있다.

기본적인 작동방식을 살펴보면

from collections import defaultdict    # 외부함수이기 때문에 import 해야한다.

int_dict = defaultdict(int)

print(int_dict) # defaultdict(<class 'int'>, {})          # 디폴트값이 int인 딕셔너리

위와 같이 설정을 하면 값을 지정하지 않은 키는 그 값이 0으로 지정된다.

int_dict['key1'] # 0

print(int_dict) # defaultdict(<class 'int'>, {'key1': 0})

키에 명시적으로 값을 지정하게 되면 그 값이 지정된다.

int_dict['key2'] = 'test'

print(int_dict) # defaultdict(<class 'int'>, {'key1': 0, 'key2': 'test'})

defaultdict라는 말 그대로 처음 키를 지정할 때 값을 주지 않으면 해당 키에 대한 값을 디폴트 값을 지정하겠다는 뜻이다.

리스트, 셋을 디폴트 값으로 지정해 보자.

default 값으로 list를 줬을때 작동방식

list_dict = defaultdict(list)

print(list_dict) #defaultdict(<class 'list'>, {})     # 디폴트값이 list인 딕셔너리

print(list_dict['key1'])    # 값을 지정하지 않으면 빈 리스트로 초기화.  []

list_dict['key2'] = 'test'     # 값을 지정하면 해당값으로 초기화

print(list_dict)  # defaultdict(<class 'list'>, {'key1': [], 'key2': 'test'})

default 값으로 set을 줬을때 작동방식

set_dict = defaultdict(set)

print(set_dict) # defaultdict(<class 'set'>, {})                                     # 디폴트값이 set인 딕셔너리

set_dict['key1']    # 값을 지정하지 않으면 빈 리스트로 초기화. set()

set_dict['key2'] = 'test'     # 값을 지정하면 해당값으로 초기화

print(set_dict) # defaultdict(<class 'set'>, {'key1': set(), 'key2': 'test'})

자 그러면 언제 defaultdict()를 사용하는것이 좋을까?

키의 개수를 세야하는 상황이나, 리스트나 셋의 항목을 정리해야 하는 상황에 적절할것 같다.

레퍼런스에서도 그런예제들이 보통이다.

문자열에 나타난 알파벳의 횟수를 계산하는 방법을 살펴보자.

default(int) 활용예제

letters = 'dongdongfather'

letters_dict = defaultdict(int)

for k in letters:
	letters_dict[k] += 1                    #키에 대한 값이 없으면 값을 0으로 초기화

print(letters_dict) 
# defaultdict(<class 'int'>, {'d': 2, 'o': 2, 'n': 2, 'g': 2, 'f': 1, 'a': 1, 't': 1, 'h': 1, 'e': 1, 'r': 1})

딕셔너리에 키가 있는지(해당 알파벳) 확인 절차를 거칠 필요없이 바로 값을 1증가시켜주면 된다.

없으면 그 키를 만들어주고 초깃값을 0으로 세팅해 주기 때문이다.

비교를 위해 defaultdict()를 사용하지 않은 방법을 보면

defaultdict()를 사용하지 않을때

letters = 'dongdongfather'

letters_dict = {}

for k in letters:

	if not k in letters_dict:  # 키가 있는지 확인
		letters_dict[k] = 0     # 없으면 0으로 초깃값 할당
		letters_dict[k] += 1

print(letters_dict)

# {'d': 2, 'o': 2, 'n': 2, 'g': 2, 'f': 1, 'a': 1, 't': 1, 'h': 1, 'e': 1, 'r': 1}

위와 같이 키가 존재하는지 검사하는 코드와 0으로 초기화하는 코드가 추가로 필요하다.

리스트나 셋을 이용해서 여러개의 값을 합쳐야 할때도 쉽게 처리할 수 있다.

다음 예제에서 내가 하고 싶은것은 주어진 성과 이름 튜플에서 각 성에 대해 어떤 이름들이 있는가 분류하는것이다.

defaultdict(list) 활용예제

name_list = [('kim','sungsu'), ('kang','hodong'), ('park','jisung'), ('kim','yuna'), ('park','chanho'), ('kang','hodong')]

ndict = defaultdict(list)

for k, v in name_list:   # 리스트의 요소가 튜플이기 때문에 k, v값으로 할당
	ndict[k].append(v)        # 값이 리스트이기때문에 append()를 이용해서 항목추가

print(ndict)

# defaultdict(<class 'list'>, {'kim': ['sungsu', 'yuna'], 'kang': ['hodong', 'hodong'], 'park': ['jisung', 'chanho']})

이렇게 간단하게 각 성이 가진 이름을 취합할 수 있다.

위 리스트에 보면 name_list에서 'kang hodong'이 두번 나왔기때문에 딕셔너리에서도 'hodong'이 두번 출력된걸 알 수 있다.

보통 이런 중복자료는 의미가 없기때문에 없애주고 싶다.

이럴때 set을 기본값으로 주면 바로 해결된다.

set은 중복값을 허용하지 않기 때문이다.

defaultdict(set) 활용예제

name_list = [('kim','sungsu'), ('kang','hodong'), ('park','jisung'), ('kim','yuna'), ('park','chanho'), ('kang','hodong')]

nset = defaultdict(set)                       # 초깃값을 셋으로 설정

for k, v in name_list:
	ndict[k].add(v)    # list는 append()를 사용해서 항목추가. set은 add()를 사용해서 항목추가

print(ndict)

# defaultdict(<class 'set'>, {'kim': {'sungsu', 'yuna'}, 'kang': {'hodong'}, 'park': {'jisung', 'chanho'}})

'Engineering WIKI > Python' 카테고리의 다른 글

파이썬 퀵 정렬  (0) 2022.05.25
Python3 vs Pypy3  (0) 2022.05.25
Python TDD  (0) 2022.05.23
파이썬 상속 (Inheritance)  (0) 2022.05.23
문자열 split() 과 split(" ") 차이  (0) 2022.05.19
함수 주석  (0) 2022.05.17
any, all 함수  (0) 2022.05.17
operator의 itemgetter를 사용해서 리스트 정렬  (0) 2022.05.17