
파이썬 setdefault와 defaultdict 차이는 결국 기본값을 언제, 어디서 준비하느냐에 있습니다. setdefault()는 일반 dict에서 필요할 때 키를 넣고 그 값을 돌려주고, defaultdict는 없는 키를 만나면 어떤 기본값을 만들지 규칙을 미리 선언해둡니다.
먼저 핵심부터 말하면 setdefault는 호출 지점에서 초기화하고, defaultdict는 딕셔너리 생성 시점에 초기화 규칙을 등록합니다.

파이썬 setdefault와 defaultdict 차이 한 줄로 구분하기
- setdefault: 일반 dict에 없는 키가 나오면 기본값을 넣고 그 값을 반환한다
- defaultdict: 없는 키를 만났을 때 어떤 기본값을 만들지 factory를 미리 등록해둔다
둘 다 딕셔너리 초기화 코드를 줄이려는 목적은 비슷하지만, 읽기 흐름과 실수 포인트는 꽤 다릅니다.
setdefault는 어떻게 읽어야 할까
Python 공식 문서에 따르면 dict.setdefault(key, default)는 키가 있으면 기존 값을 반환하고, 없으면 default를 넣고 그 값을 반환합니다.
groups = {}
groups.setdefault("python", []).append("dict")
groups.setdefault("python", []).append("set")
print(groups)즉 setdefault는 지금 이 줄에서 필요하니 그 자리에서 기본값을 만들어 넣는 방식으로 읽으면 됩니다.
defaultdict는 어떻게 읽어야 할까
Python 공식 문서는 defaultdict를 missing key에 대해 factory function을 호출해 기본값을 공급하는 dict subclass로 설명합니다.
from collections import defaultdict
groups = defaultdict(list)
groups["python"].append("dict")
groups["python"].append("set")
print(groups)여기서는 list가 기본값 생성 규칙입니다. 없는 키를 d[key]로 접근하면 빈 리스트를 만들고 저장한 뒤 반환합니다.
같은 grouping 코드로 비교해보자
fruits = ["apple", "apricot", "banana", "blueberry", "avocado"]
groups = {}
for fruit in fruits:
groups.setdefault(fruit[0], []).append(fruit)
print(groups)이 코드는 compact하지만 반복문 안에서 setdefault(..., []) 패턴이 계속 등장합니다.
from collections import defaultdict
fruits = ["apple", "apricot", "banana", "blueberry", "avocado"]
groups = defaultdict(list)
for fruit in fruits:
groups[fruit[0]].append(fruit)
print(groups)이 버전은 핵심 로직이 더 앞에 보입니다. 같은 초기화 규칙이 반복될수록 defaultdict 쪽이 더 읽기 쉬운 경우가 많습니다.

counting에서도 차이가 잘 보인다
words = ["apple", "banana", "apple", "orange", "banana", "apple"]
counts = {}
for word in words:
counts[word] = counts.setdefault(word, 0) + 1
print(counts)이렇게 쓸 수는 있지만 초심자 입장에서는 읽을 때 잠깐 멈칫할 수 있습니다.
from collections import defaultdict
words = ["apple", "banana", "apple", "orange", "banana", "apple"]
counts = defaultdict(int)
for word in words:
counts[word] += 1
print(counts)defaultdict(int)는 처음 보는 키를 0으로 시작하게 해주므로 counting에서 특히 읽기 좋습니다.
주의점 1: defaultdict는 조회하다가 키를 만들 수 있다
defaultdict는 d[key] 접근에서 자동 생성이 일어납니다. 조회만 했다고 생각했는데 키가 생길 수 있다는 뜻입니다.
from collections import defaultdict
d = defaultdict(list)
print(d["python"])
print(d)주의점 2: get()은 default_factory를 쓰지 않는다
Python 공식 문서는 __missing__이 __getitem__ 경로에서만 호출된다고 설명합니다. 그래서 d[key]와 d.get(key)는 다르게 동작합니다.
from collections import defaultdict
d = defaultdict(list)
print(d.get("python")) # None
print(d) # 아직 비어 있음
print(d["python"]) # []
print(d) # 이제 키가 생김조회만 하고 싶다면 get()이 더 안전할 수 있고, 없으면 실제 버킷을 만들고 이어서 작업할 생각이면 d[key]가 잘 맞습니다.
그럼 언제 setdefault가 더 나을까
- 일반 dict를 이미 쓰고 있고 특정 한두 군데에서만 기본값 삽입이 필요할 때
- 작은 스크립트에서 짧게 끝내고 싶을 때
- 반복 규칙 전체를 구조로 선언할 정도는 아닐 때
즉 setdefault는 가끔 필요한 현장 삽입에 가깝고, defaultdict는 반복 패턴을 구조로 선언하는 쪽에 가깝습니다.
함께 보면 좋은 글과 공식 문서
관련 기본기를 더 정리하고 싶다면 파이썬 defaultdict 쉽게 이해하기, 파이썬 is와 == 차이도 같이 읽어보면 좋습니다.
공식 기준은 collections.defaultdict 문서와 dict.setdefault 문서를 참고하면 됩니다.
결론: 반복 규칙이면 defaultdict, 현장 삽입이면 setdefault가 읽기 쉽다
파이썬 setdefault와 defaultdict 차이는 단순 취향보다 코드 구조 차이에 가깝습니다. setdefault는 호출하는 자리에서 기본값을 넣는 방식이고, defaultdict는 딕셔너리를 만들 때부터 기본값 생성 규칙을 선언하는 방식입니다. 반복되는 grouping과 counting이라면 defaultdict가 더 읽기 좋은 경우가 많고, 짧은 초기화 한두 번이라면 setdefault도 충분히 좋은 선택입니다.