딕셔너리에서 값을 조회할 때는 키가 없다는 상황부터 구분해야 한다. 반드시 존재해야 하는 키가 누락된 경우와, 없어도 정상인 선택 항목은 처리 방식이 달라야 한다.
d[key]는 없는 키를 조회하면 KeyError를 발생시킨다. 반면 d.get(key, default)는 키가 없을 때 지정한 기본값을 반환한다. 기본값을 생략하면 None을 반환한다.
scores = {"python": 80, "sql": 0}
print(scores.get("python", -1))
print(scores.get("sql", -1))
print(scores.get("git", -1))
print("git" in scores)
80
0
-1
False
git이 없으므로 -1을 반환하지만, 딕셔너리에 새 항목이 추가되지는 않는다. sql의 값인 0도 그대로 유지된다. 기본값은 값이 거짓으로 평가될 때가 아니라 키 자체가 없을 때 사용된다.
scores = {"sql": 0}
print(scores.get("sql", 50))
print(scores.get("sql") or 50)
0
50
첫 번째 식은 실제 점수 0을 보존한다. 두 번째 식은 0이 거짓으로 평가되므로 50을 선택한다. 0점이 유효한 값인 상황에서 두 식을 바꿔 쓰면 데이터의 의미가 달라진다.
profile = {"nickname": None}
print(profile.get("nickname", "anonymous"))
print(profile.get("city", "unknown"))
print("nickname" in profile)
print("city" in profile)
None
unknown
True
False
nickname이라는 키는 이미 존재한다. 따라서 저장된 None을 반환한다. 키의 존재 여부를 알고 싶다면 반환값을 추측하기보다 in으로 확인하는 편이 명확하다.
d[key]로 문제를 드러낸다.get()에 의미 있는 기본값을 지정한다.None을 구분해야 한다면 in 등으로 별도 확인한다.예를 들어 필수 설정이 빠졌는데 무조건 빈 문자열을 반환하면, 오류가 사라진 것이 아니라 발견 시점만 늦어진다. 기본값은 예외를 피하기 위한 장식이 아니라 누락된 데이터의 의미를 표현하는 선택이다.
get()을 사용할 때 확인할 것은 세 가지다. 없는 키가 허용되는지, 0이나 None이 실제 값으로 가능한지, 조회와 동시에 저장할 필요가 있는지다. 이 조건을 정리하면 짧은 코드 때문에 데이터의 의미를 놓치는 일을 줄일 수 있다.