일반적인 딕셔너리(dict)만으로도 충분히 강력하지만, 파이썬의 표준 라이브러리인 collections 모듈을 사용하면 더욱 편리한 확장판 딕셔너리를 사용할 수 있다. 그중 가장 대표적인 defaultdict와 Counter를 정리한다.
🐍 파이썬 딕셔너리의 진화: defaultdict와 Counter
데이터를 처리하다 보면 "키가 없을 때 자동으로 기본값을 넣어주면 좋겠다"거나 "개수를 자동으로 세어주면 좋겠다"는 상황이 발생한다. 이때 collections 모듈의 도구들을 활용한다.
1. defaultdict: 키 에러(KeyError) 없는 딕셔너리
일반 딕셔너리는 존재하지 않는 키를 호출하면 에러가 발생한다. 하지만 defaultdict는 키가 없을 경우 사용자가 미리 지정한 기본값(default value)을 자동으로 생성해준다.
생성 및 사용법
defaultdict(기본값_생성_함수) 형태로 선언한다.
from collections import defaultdict
# 기본값을 리스트([])로 설정한 defaultdict
list_dict = defaultdict(list)
# 'fruits'라는 키가 없어도 바로 append 가능
list_dict['fruits'].append('apple')
list_dict['fruits'].append('banana')
print(list_dict)
# 결과: defaultdict(<class 'list'>, {'fruits': ['apple', 'banana']})
왜 쓰는가?
일반 딕셔너리에서 위와 같은 작업을 하려면 if key not in d: d[key] = [] 처럼 키의 존재 여부를 매번 확인해야 하지만, defaultdict를 쓰면 코드가 훨씬 간결해진다. 주로 데이터를 그룹화할 때(예: int로 카운팅, list로 모으기) 유용하다.
dd = defaultdict(int)
# 아직 `apple`이라는 key값에 해당하는 value를 만들어주지 않았으나 += 1 연산이 가능함.
dd['apple'] += 1
dd['banana'] += 2
print("defaultdict 결과:", dict(dd)) # {'apple': 1, 'banana': 2}
API 읽어보기
기본 사용법에 대해 위에 설명했지만 사실 vscode에서 팝업되는 내용은 자바 개발자 입장에서 난해하기 짝이 없었다. 이걸 해석해보자.
class defaultdict(
default_factory: (() -> _VT@defaultdict) | None,
/
)
파라미터의 타입으로는 default_factory 또는 None이 들어올 수 있다.
- default_factory는 호출 가능한 객체 또는 None이다. (()->T)는 인자없이 호출해서 T를 반환하는 함수이다. 마치 Java의 Supplier와 같다. _VT@defaultdict는 python 내부 타입 변수 표기로 그냥 dictionary의 value type으로 사용되는 값 정도로 이해하면 된다.
- / 는 이 앞의 인자들이 위치 전용이라는 뜻이다. 즉 default_factory = int 와 같이 사용하면 안된다.
2. Counter: 개수 세기의 끝판왕
Counter는 이름 그대로 요소의 개수를 세기 위해 최적화된 자료형이다. 리스트나 문자열을 넣어주면 각 요소가 몇 번 등장하는지 자동으로 계산하여 딕셔너리 형태로 저장한다.
생성 및 사용법
from collections import Counter
words = ["apple", "banana", "apple", "cherry", "banana", "apple"]
count_result = Counter(words)
print(count_result)
# 결과: Counter({'apple': 3, 'banana': 2, 'cherry': 1})
# 문자열을 바로 넣어도 된다
print(Counter("mississippi"))
# 결과: Counter({'i': 4, 's': 4, 'p': 2, 'm': 1})
Counter의 강력한 기능
- 가장 많이 등장한 요소 찾기:
most_common(n)을 사용하여 상위 n개를 뽑아낼 수 있다.
- 산술 연산: 집합처럼 Counter 객체끼리 더하거나 빼는 연산이 가능하다.
c = Counter(apple=3, banana=1)
d = Counter(apple=1, banana=2)
print(c + d) # Counter({'apple': 4, 'banana': 3})
print(c - d) # Counter({'apple': 2}) (결과가 0 이하는 제외됨)
# 가장 빈도수가 높은 상위 1개 추출
print(Counter("abracadabra").most_common(1)) # [('a', 5)]
3. 요약 및 비교
| 특징 |
defaultdict |
Counter |
| 주요 목적 |
키가 없을 때의 초기값 자동 설정 |
요소의 빈도수(개수) 측정 |
| 초기화 방식 |
defaultdict(list), defaultdict(int) 등 |
Counter(리스트) 또는 Counter(문자열) |
| 주요 활용 |
데이터 그룹화, 복잡한 딕셔너리 구조 생성 |
빈도 분석, 중복 제거, 랭킹 산출 |
4. 마무리
- defaultdict는 존재하지 않는 키에 접근할 때 발생하는 예외 처리를 생략하고 싶을 때 사용한다.
- Counter는 데이터 내 요소들의 출현 빈도를 계산하고 순위를 매겨야 할 때 사용한다.
이 두 가지 도구는 파이썬 코딩 테스트나 데이터 분석 실무에서 코드를 대폭 줄여주는 핵심 도구이므로 반드시 익혀두는 것이 좋다.