Python 딕셔너리 병합, 3.5 이상에서 언패킹 연산자 활용
문제 상황
데이터 파이프라인을 리팩토링하던 중 딕셔너리 병합 로직이 여러 방식으로 섞여 있었다. update(), dict() 생성자, 반복문 등 코드마다 제각각이었고, 특히 불변성을 보장해야 하는 부분에서 문제가 있었다.
기존 방식들
# 방식 1: update() - 원본 수정
config = {'host': 'localhost'}
config.update({'port': 5432})
# 방식 2: dict() 생성자
config = dict(base_config, **override_config)
# 방식 3: copy + update
config = base_config.copy()
config.update(override_config)
첫 번째는 원본을 수정하고, 두 번째는 키가 문자열이어야 하며, 세 번째는 두 줄이 필요했다.
언패킹 연산자 사용
Python 3.5부터 ** 연산자로 딕셔너리를 언패킹할 수 있다.
base_config = {'host': 'localhost', 'port': 5432}
override_config = {'port': 3306, 'user': 'admin'}
config = {**base_config, **override_config}
# {'host': 'localhost', 'port': 3306, 'user': 'admin'}
- 원본을 수정하지 않음
- 한 줄로 표현 가능
- 여러 딕셔너리 병합 가능
- 순서대로 덮어쓰기
실제 적용 사례
DB 연결 설정을 환경별로 오버라이드하는 코드를 정리했다.
DEFAULT_CONFIG = {
'host': 'localhost',
'port': 5432,
'pool_size': 10,
}
def get_db_config(env):
env_configs = {
'dev': {'host': 'dev-db.internal'},
'prod': {'host': 'prod-db.internal', 'pool_size': 50},
}
return {**DEFAULT_CONFIG, **env_configs.get(env, {})}
코드가 훨씬 명확해졌고, 팀 내에서도 이 방식으로 통일하기로 했다. Python 3.5 이상을 사용하고 있다면 이제 이 방식이 표준이라고 봐도 될 것 같다.