파이썬의 딕셔너리(Dictionary)는 가변적이고 순서가 없는(unordered) 데이터 타입으로, 키(key)와 값(value)의 쌍으로 데이터를 저장합니다. 이는 문자열, 리스트, 튜플과 같은 다른 자료형과 비교했을 때 중요한 차이점을 가집니다. 예를 들어, 문자열, 리스트, 튜플은 순서가 있어 인덱스나 슬라이싱을 통해 요소에 접근할 수 있지만, 딕셔너리는 순서가 없으므로 키를 통해서만 값에 접근할 수 있습니다.
딕셔너리는 키-값 쌍(key-value pair) 형태로 데이터를 구성합니다. 여기서 키는 고유하며 불변(immutable)한 객체여야 합니다. 따라서 문자열, 숫자, 튜플 등은 키로 사용될 수 있지만, 가변적인 리스트는 키로 사용할 수 없습니다. 값은 어떤 종류의 객체든 될 수 있습니다. 각 키-값 쌍은 콜론(:)으로 구분하며, 여러 쌍은 쉼표(,)로 구분하고 전체 딕셔너리는 중괄호({ })로 감싸서 표현합니다.
# 딕셔너리 예시
user_info = {"name": "김민준", "age": 25, "city": "서울"}
print(user_info)
# 출력: {'name': '김민준', 'age': 25, 'city': '서울'}
1. 딕셔너리 생성 방법
1.1. 중괄호 { } 사용
가장 일반적인 방법으로, 키-값 쌍을 직접 중괄호 안에 작성하여 딕셔너리를 생성합니다.
# 중괄호를 이용한 딕셔너리 생성
product_details = {"item_id": "P001", "name": "무선 이어폰", "price": 120000}
print(product_details)
# 출력: {'item_id': 'P001', 'name': '무선 이어폰', 'price': 120000}
1.2. dict() 함수 사용
파이썬 내장 함수 dict()는 다양한 방식으로 딕셔너리 객체를 생성할 수 있도록 지원합니다.
1.2.1. 키워드 인수를 통해 생성
dict(key1=value1, key2=value2, ...) 형태로 키워드 인수를 사용하여 딕셔너리를 생성할 수 있습니다. 이때 키는 문자열이지만 따옴표 없이 바로 이름을 사용합니다.
# 키워드 인수를 사용한 딕셔너리 생성
student_record = dict(student_id=2023001, major="컴퓨터공학", grade="A")
print(student_record)
# 출력: {'student_id': 2023001, 'major': '컴퓨터공학', 'grade': 'A'}
1.2.2. 빈 딕셔너리 생성
인수 없이 dict()를 호출하면 빈 딕셔너리를 생성할 수 있습니다.
# 빈 딕셔너리 생성
empty_data = dict()
print(empty_data)
# 출력: {}
1.2.3. 다른 딕셔너리 객체를 통해 생성 (얕은 복사)
기존 딕셔너리 객체를 dict() 함수에 전달하여 새로운 딕셔너리를 생성할 수 있습니다. 이는 기존 딕셔너리의 얕은 복사본을 만듭니다.
# 기존 딕셔너리로부터 복사 생성
original_config = {'theme': 'dark', 'font_size': 14}
copied_config = dict(original_config)
print(f"원본 딕셔너리: {original_config}")
print(f"복사된 딕셔너리: {copied_config}")
print(f"원본 딕셔너리 ID: {id(original_config)}")
print(f"복사된 딕셔너리 ID: {id(copied_config)}")
# 출력:
# 원본 딕셔너리: {'theme': 'dark', 'font_size': 14}
# 복사된 딕셔너리: {'theme': 'dark', 'font_size': 14}
# 원본 딕셔너리 ID: (일부 숫자)
# 복사된 딕셔너리 ID: (일부 숫자, 원본과 다름)
위 예시에서 볼 수 있듯이, 두 딕셔너리는 내용이 같지만 메모리상의 다른 객체임을 확인할 수 있습니다.
1.2.4. 키-값 쌍의 이터러블(iterable)을 통해 생성
dict() 함수는 (key, value) 형태의 튜플 또는 리스트를 요소로 갖는 리스트나 튜플과 같은 이터러블을 인수로 받아 딕셔너리를 생성할 수 있습니다. 각 내부 시퀀스는 정확히 두 개의 요소를 가져야 합니다.
# 튜플 리스트를 통한 생성
employee_skills = dict([('Python', 'Expert'), ('SQL', 'Intermediate'), ('Cloud', 'Basic')])
print(f"튜플 리스트에서 생성: {employee_skills}")
# 리스트 리스트를 통한 생성
team_scores = dict([['Alpha', 85], ['Beta', 92], ['Gamma', 78]])
print(f"리스트 리스트에서 생성: {team_scores}")
# 출력:
# 튜플 리스트에서 생성: {'Python': 'Expert', 'SQL': 'Intermediate', 'Cloud': 'Basic'}
# 리스트 리스트에서 생성: {'Alpha': 85, 'Beta': 92, 'Gamma': 78}
2. 딕셔너리 값 접근
딕셔너리는 순서가 없으므로 정수 인덱싱이나 슬라이싱으로 값에 접근할 수 없습니다. 대신 키를 사용하여 해당 값에 접근합니다. 값에 접근하는 주요 방법은 두 가지입니다.
# 예시 딕셔너리
product_details = {'name': '스마트 워치', 'price': 250000, 'manufacturer': 'TechCorp'}
2.1. 대괄호 [key] 사용
딕셔너리 이름 뒤에 대괄호 []를 사용하고 그 안에 키를 지정하여 값에 접근합니다. 키가 딕셔너리에 존재하지 않으면 KeyError가 발생합니다.
print(product_details['name']) # 스마트 워치
print(product_details['price']) # 250000
# print(product_details['stock']) # KeyError: 'stock' 발생
2.2. get(key) 메서드 사용
get() 메서드는 키가 존재하지 않을 경우 KeyError를 발생시키지 않고 None을 반환합니다. 또한 두 번째 인수로 기본값을 제공하여 키가 없을 때 반환될 값을 지정할 수 있습니다.
print(product_details.get('name')) # 스마트 워치
print(product_details.get('price')) # 250000
print(product_details.get('stock')) # None (키가 없으므로 None 반환)
print(product_details.get('stock', 0)) # 0 (키가 없으면 기본값 0 반환)
get() 메서드는 키 존재 여부를 미리 확인하지 않고 안전하게 값을 가져올 때 유용합니다.
3. 딕셔너리 데이터 수정
3.1. 값 추가 및 수정
새로운 키-값 쌍을 추가하거나 기존 키의 값을 수정하는 방법은 동일합니다. 존재하지 않는 키에 값을 할당하면 새로운 키-값 쌍이 추가되고, 존재하는 키에 값을 할당하면 해당 키의 값이 변경됩니다.
user_data = {'username': 'coder123', 'email': 'coder@example.com'}
print(f"초기 딕셔너리: {user_data}")
# 새로운 키-값 쌍 추가
user_data['country'] = '대한민국'
print(f"country 추가 후: {user_data}")
# 기존 키의 값 수정
user_data['email'] = 'new_coder@example.com'
print(f"email 수정 후: {user_data}")
여러 키-값 쌍을 한 번에 추가하거나 업데이트하려면 update() 메서드를 사용합니다. 이 메서드는 다른 딕셔너리나 키-값 쌍의 이터러블을 인수로 받습니다.
user_data.update({'age': 30, 'gender': '남'})
print(f"update() 후: {user_data}")
# 출력: {'username': 'coder123', 'email': 'new_coder@example.com', 'country': '대한민국', 'age': 30, 'gender': '남'}
3.2. 값 삭제
딕셔너리에서 키-값 쌍을 삭제하는 방법에는 여러 가지가 있습니다.
3.2.1. del 키워드 사용
del 키워드를 사용하여 특정 키에 해당하는 키-값 쌍을 삭제할 수 있습니다. 키가 존재하지 않으면 KeyError가 발생합니다.
current_settings = {'mode': 'light', 'language': 'ko', 'notifications': True}
print(f"초기 설정: {current_settings}")
del current_settings['notifications']
print(f"notifications 삭제 후: {current_settings}")
# 출력: {'mode': 'light', 'language': 'ko'}
3.2.2. pop(key) 메서드 사용
pop() 메서드는 지정된 키에 해당하는 키-값 쌍을 삭제하고, 해당 키의 값을 반환합니다. 키가 존재하지 않을 경우 KeyError를 발생시키지만, 두 번째 인수로 기본값을 제공하면 키가 없을 때 그 기본값을 반환합니다.
profile_data = {'id': 101, 'name': '이수진', 'status': 'active'}
print(f"초기 프로필: {profile_data}")
removed_status = profile_data.pop('status')
print(f"삭제된 status: {removed_status}, 현재 프로필: {profile_data}")
# 출력: 삭제된 status: active, 현재 프로필: {'id': 101, 'name': '이수진'}
# 존재하지 않는 키 삭제 시도 (기본값 제공)
non_existent_value = profile_data.pop('address', 'Unknown')
print(f"존재하지 않는 키 삭제 (기본값): {non_existent_value}, 현재 프로필: {profile_data}")
# 출력: 존재하지 않는 키 삭제 (기본값): Unknown, 현재 프로필: {'id': 101, 'name': '이수진'}
3.2.3. clear() 메서드 사용
clear() 메서드는 딕셔너리 내의 모든 키-값 쌍을 제거하여 딕셔너리를 비웁니다.
temp_storage = {'data1': 'A', 'data2': 'B'}
print(f"초기 임시 저장소: {temp_storage}")
temp_storage.clear()
print(f"clear() 후: {temp_storage}")
# 출력: {}
3.3. 키 존재 여부 확인
in 연산자를 사용하여 특정 키가 딕셔너리에 존재하는지 확인할 수 있습니다. 키가 존재하면 True, 존재하지 않으면 False를 반환합니다.
device_info = {'type': 'tablet', 'model': 'GalaxyTab', 'os': 'Android'}
print(f"'type' 키 존재 여부: {'type' in device_info}") # True
print(f"'screen_size' 키 존재 여부: {'screen_size' in device_info}") # False
4. 딕셔너리 주요 메서드
4.1. keys()
딕셔너리의 모든 키를 포함하는 뷰(view) 객체를 반환합니다. 이 뷰 객체는 딕셔너리의 키 변화를 반영합니다.
inventory = {'item_A': 100, 'item_B': 50, 'item_C': 200}
print(f"인벤토리 키: {inventory.keys()}")
# 출력: dict_keys(['item_A', 'item_B', 'item_C'])
4.2. values()
딕셔너리의 모든 값을 포함하는 뷰 객체를 반환합니다. 이 뷰 객체는 딕셔너리의 값 변화를 반영합니다.
print(f"인벤토리 값: {inventory.values()}")
# 출력: dict_values([100, 50, 200])
4.3. items()
딕셔너리의 모든 키-값 쌍을 (key, value) 형태의 튜플로 포함하는 뷰 객체를 반환합니다. 이 뷰 객체는 딕셔너리의 변화를 반영합니다.
print(f"인벤토리 아이템: {inventory.items()}")
# 출력: dict_items([('item_A', 100), ('item_B', 50), ('item_C', 200)])
4.4. len(dict)
딕셔너리의 키-값 쌍의 개수(길이)를 반환합니다.
print(f"인벤토리 아이템 수: {len(inventory)}")
# 출력: 3
4.5. copy()
딕셔너리의 얕은 복사본을 생성하여 반환합니다. 원본 딕셔너리와는 별개의 새로운 딕셔너리 객체입니다.
original_preferences = {'notification': True, 'theme': 'dark'}
copied_preferences = original_preferences.copy()
print(f"원본: {original_preferences}, ID: {id(original_preferences)}")
print(f"복사본: {copied_preferences}, ID: {id(copied_preferences)}")
# 원본 딕셔너리 수정
original_preferences['theme'] = 'light'
print(f"원본 수정 후 원본: {original_preferences}")
print(f"원본 수정 후 복사본: {copied_preferences}")
# 출력:
# 원본: {'notification': True, 'theme': 'dark'}, ID: (일부 숫자)
# 복사본: {'notification': True, 'theme': 'dark'}, ID: (일부 숫자, 원본과 다름)
# 원본 수정 후 원본: {'notification': True, 'theme': 'light'}
# 원본 수정 후 복사본: {'notification': True, 'theme': 'dark'}
위 예시에서 볼 수 있듯이, copy()로 생성된 딕셔너리는 원본과 독립적이며, 원본의 변경이 복사본에 영향을 주지 않습니다 (내부 mutable 객체를 포함하지 않는 한).
4.6. list(dict)
딕셔너리를 list() 함수에 인수로 전달하면, 딕셔너리의 모든 키를 포함하는 리스트가 반환됩니다.
course_grades = {'Math': 'A', 'Science': 'B+', 'History': 'A'}
print(f"과목 키 리스트: {list(course_grades)}")
# 출력: ['Math', 'Science', 'History']