딕셔너리에 키-값 쌍을 추가하는 메서드는 두 가지가 있습니다.
| 메서드 | 기능 | 키가 이미 있을 때 |
|---|---|---|
setdefault(키, 값) | 키-값 쌍 추가 | 기존 값 유지 |
update(키=값) | 키-값 쌍 추가 또는 값 수정 | 새 값으로 덮어씀 |
setdefault는 키가 없으면 추가하고, 이미 있으면 기존 값을 유지합니다. 기본값을 지정하지 않으면 None이 들어갑니다.
d = {"a": 1, "b": 2}
# 키가 없으면 추가
d.setdefault("c", 3)
print(d) # {'a': 1, 'b': 2, 'c': 3}
# 키가 이미 있으면 기존 값 유지
d.setdefault("a", 999)
print(d) # {'a': 1, 'b': 2, 'c': 3} ← 'a'는 여전히 1
# 기본값을 지정하지 않으면 None
d.setdefault("d")
print(d) # {'a': 1, 'b': 2, 'c': 3, 'd': None}
update는 키가 있으면 값을 수정하고, 키가 없으면 새로 추가합니다. 여러 개를 한 번에 수정하는 것도 가능합니다.
d = {"a": 1, "b": 2}
# 키의 값 수정
d.update(a=10)
print(d) # {'a': 10, 'b': 2}
# 여러 개를 한 번에 수정
d.update(a=100, b=200, c=300)
print(d) # {'a': 100, 'b': 200, 'c': 300}
update는 다양한 형태의 인자를 받을 수 있습니다. 특히 키가 숫자일 때는 키=값 형태를 쓸 수 없으므로 딕셔너리나 리스트, 튜플을 넣어서 수정합니다.
d = {1: "one", 2: "two"}
# 딕셔너리를 넣어서 수정 (키가 숫자일 때)
d.update({1: "하나", 3: "셋"})
print(d) # {1: '하나', 2: 'two', 3: '셋'}
# 리스트로 수정 (키-값 쌍의 리스트)
d.update([[2, "둘"]])
print(d) # {1: '하나', 2: '둘', 3: '셋'}
# 튜플로도 가능
d.update([(3, "three")])
print(d) # {1: '하나', 2: '둘', 3: 'three'}
| 방법 | 기능 | 반환값 |
|---|---|---|
pop(키) | 특정 키-값 쌍 삭제 | 삭제한 값 반환 |
del 딕셔너리[키] | 특정 키-값 쌍 삭제 | 반환값 없음 |
clear() | 모든 키-값 쌍 삭제 | 반환값 없음 |
d = {"a": 1, "b": 2, "c": 3}
# pop: 삭제 후 값 반환
value = d.pop("a")
print(value) # 1
print(d) # {'b': 2, 'c': 3}
# del: 단순 삭제
del d["b"]
print(d) # {'c': 3}
# clear: 모든 키-값 쌍 삭제
d.clear()
print(d) # {}
💡
pop에 두 번째 인자로 기본값을 지정하면, 키가 없을 때 에러 대신 기본값을 반환합니다:d.pop("x", 0)→0
get(키)는 딕셔너리에서 특정 키의 값을 가져옵니다. 딕셔너리[키]와 비슷하지만, 키가 없을 때 에러가 발생하지 않는다는 차이가 있습니다.
d = {"a": 1, "b": 2}
# get: 키가 없으면 None 반환 (에러 없음)
print(d.get("a")) # 1
print(d.get("x")) # None
print(d.get("x", 0)) # 0 (기본값 지정 가능)
# 대괄호: 키가 없으면 KeyError 발생
# print(d["x"]) # KeyError: 'x'
딕셔너리는 키와 값을 가져오는 세 가지 메서드를 제공합니다.
| 메서드 | 반환값 |
|---|---|
items() | 키-값 쌍을 모두 가져옴 |
keys() | 키를 모두 가져옴 |
values() | 값을 모두 가져옴 |
d = {"name": "홍길동", "age": 25, "city": "서울"}
print(d.items()) # dict_items([('name', '홍길동'), ('age', 25), ('city', '서울')])
print(d.keys()) # dict_keys(['name', 'age', 'city'])
print(d.values()) # dict_values(['홍길동', 25, '서울'])
dict.fromkeys에 키가 담긴 리스트를 넣으면 딕셔너리를 간편하게 생성할 수 있습니다.
# fromkeys로 딕셔너리 생성 (기본값 None)
keys = ["a", "b", "c"]
d = dict.fromkeys(keys)
print(d) # {'a': None, 'b': None, 'c': None}
# 기본값 지정
d = dict.fromkeys(keys, 0)
print(d) # {'a': 0, 'b': 0, 'c': 0}
items()를 활용하면 키와 값을 동시에 가져올 수 있습니다.
# for문으로 키와 값을 함께 출력
d = {"name": "홍길동", "age": 25, "city": "서울"}
for key, value in d.items():
print(f"{key}: {value}")
# name: 홍길동
# age: 25
# city: 서울
리스트와 마찬가지로 딕셔너리도 for 반복문과 if 조건문을 사용하여 생성할 수 있습니다.
# 기본 딕셔너리 컴프리헨션
squares = {x: x ** 2 for x in range(5)}
print(squares) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
# if 조건 추가: 짝수만 필터링
even_squares = {x: x ** 2 for x in range(10) if x % 2 == 0}
print(even_squares) # {0: 0, 2: 4, 4: 16, 6: 36, 8: 64}
딕셔너리를 for 반복문으로 순회하면서 직접 키-값 쌍을 삭제하면 에러가 발생합니다. 딕셔너리의 크기가 반복 중에 바뀌기 때문입니다.
d = {"a": 1, "b": 2, "c": 3, "d": 4}
# ❌ 반복 중 직접 삭제 → RuntimeError
# for key in d:
# if d[key] > 2:
# del d[key] # RuntimeError: dictionary changed size during iteration
이럴 때는 삭제할 키-값 쌍을 제외하고 새 딕셔너리를 만드는 방식을 사용합니다. 딕셔너리 컴프리헨션이 이 문제를 깔끔하게 해결해줍니다.
# ✅ 컴프리헨션으로 조건에 맞는 요소만 남기기
d = {"a": 1, "b": 2, "c": 3, "d": 4}
d = {key: value for key, value in d.items() if value <= 2}
print(d) # {'a': 1, 'b': 2}
딕셔너리의 값 부분에 다시 딕셔너리가 들어갈 수 있습니다. 내부 딕셔너리에 접근하려면 [] 대괄호를 단계만큼 반복해서 붙이고 키를 지정합니다.
# 중첩 딕셔너리
students = {
"student1": {"name": "홍길동", "score": 90},
"student2": {"name": "김철수", "score": 85}
}
# 접근: 대괄호를 단계만큼 사용
print(students["student1"]["name"]) # 홍길동
print(students["student2"]["score"]) # 85
# 값 수정
students["student1"]["score"] = 95
print(students["student1"]) # {'name': '홍길동', 'score': 95}
리스트와 마찬가지로, 딕셔너리에도 할당, 얕은 복사, 깊은 복사의 개념이 동일하게 적용됩니다.
import copy
# 얕은 복사: 중첩된 딕셔너리는 공유됨
original = {"a": {"x": 1}, "b": 2}
shallow = original.copy()
shallow["a"]["x"] = 999
print(original["a"]["x"]) # 999 ← 원본도 변경됨!
# 깊은 복사: 완전히 독립
original = {"a": {"x": 1}, "b": 2}
deep = copy.deepcopy(original)
deep["a"]["x"] = 999
print(original["a"]["x"]) # 1 ← 원본은 변경되지 않음
| 구분 | copy() | copy.deepcopy() |
|---|---|---|
| 최상위 딕셔너리 | 독립 | 독립 |
| 중첩된 딕셔너리 | 원본과 공유 | 완전히 독립 |
| 사용 시점 | 단순 딕셔너리 | 중첩 딕셔너리 |