3. 자료구조

3.5. 딕셔너리

3.5.1. 딕셔너리 생성

  • 딕셔너리(dictionary)
    • 여러 개의 키-값(key-value) 쌍을 저장할 수 있는 컬렉션 자료형(collection data type)
    • 순서가 있는 매핑 자료형(mapping data type)(Python 3.7+)
    • 키(key)를 통해 값(value)을 찾는 구조
      • 키는 중복될 수 없고(해시 가능한 자료형만 가능), 값은 중복 가능함(모든 자료형 가능)
    • 한 번 생성된 이후에도 수정할 수 있는 가변형(mutable) 객체


  • 딕셔너리 생성
    • 리터럴 방식(dictionary literal)
      • {key: value}를 사용하여 딕셔너리를 직접 정의하는 방법
      • {} 안에 여러 개의 key: value 쌍을 ,로 구분하여 나열함
      • 중복된 키가 있으면 마지막에 정의한 값이 적용됨
    • 생성자 방식(dictionary constructor)
      • dict() 함수를 사용하여 딕셔너리를 생성하는 방법
      • 다른 iterable 객체(리스트, 튜플, 세트, 딕셔너리, 문자열 등)를 인수로 받아 딕셔너리를 생성할 때 유용함
        • zip() 함수를 이용하여 여러 개의 리스트나 튜플을 병렬로 묶어 키-값 쌍의 형태로 구성할 수 있음
        • enumerate() 함수를 이용하여 인덱스를 키로, 원소를 값으로 하여 쌍으로 묶어 딕셔너리를 생성할 수 있음
# 딕셔너리 생성1
dct = {'a': 1, 'b': 2, 'c': 3}
print(dct)
{'a': 1, 'b': 2, 'c': 3}
# 딕셔너리 생성2
dct = dict(a=1, b=2, c=3)
print(dct)
{'a': 1, 'b': 2, 'c': 3}
# 딕셔너리 생성3 : 키는 중복될 수 없음
dct = {'a':1, 'b': 2, 'c': 3, 'a': 4, 'b': 5}
print(dct)
{'a': 4, 'b': 5, 'c': 3}
# 딕셔너리 생성4 : (key, value) 쌍의 리스트 사용
dct = dict([('x', 100), ('y', 200)])
print(dct)
{'x': 100, 'y': 200}
# 딕셔너리 생성5 : zip() 함수 사용
keys = ['name', 'age', 'city']
values = ['Alice', 28, 'Jeonju']
dct = dict(zip(keys, values))
print(dct)
{'name': 'Alice', 'age': 28, 'city': 'Jeonju'}
# 딕셔너리 생성6 : enumerate() 함수 사용
fruits = ['apple', 'banana', 'cherry']
dct = dict(enumerate(fruits))
print(dct)
{0: 'apple', 1: 'banana', 2: 'cherry'}


3.5.2. 딕셔너리 값 접근

  • 딕셔너리는 키를 사용하여 값에 접근함
  • 리스트, 튜플처럼 정수 인덱스를 이용한 접근은 불가능함
# 키를 이용한 값 접근
info = {'name': 'Alice', 'age': 28, 'city': 'Jeonju'}
print(info['name'])
print(info['age'])
Alice
28
# 딕셔너리는 가변형 객체이므로 키를 이용한 수정이 가능함
info = {'name': 'Alice', 'age': 28, 'city': 'Jeonju'}
info['city'] = 'Iksan'
print(info)
{'name': 'Alice', 'age': 28, 'city': 'Iksan'}
# 새로운 키-값 쌍 추가
info = {'name': 'Alice', 'age': 28, 'city': 'Jeonju'}
info['email'] = 'alice123@gmail.com'
print(info)
{'name': 'Alice', 'age': 28, 'city': 'Jeonju', 'email': 'alice123@gmail.com'}


3.5.3. 딕셔너리 메소드

3.5.3.1. 딕셔너리 조회

함수 설명
keys() 딕셔너리의 모든 키를 반환(dict_keys 객체)
values() 딕셔너리의 모든 값을 반환(dict_values 객체)
items() (키, 값) 쌍을 튜플 형태로 반환(dict_items 객체)
get() 지정한 키의 값을 반환하며, 없으면 None 반환
in 연산자 특정 키가 딕셔너리에 있다면 True, 없다면 False 반환
# 모든 키
info = {'name': 'Alice', 'age': 28, 'city': 'Jeonju'}
print(list(info.keys()))
['name', 'age', 'city']
# 모든 값
info = {'name': 'Alice', 'age': 28, 'city': 'Jeonju'}
print(list(info.values()))
['Alice', 28, 'Jeonju']
# (키, 값) 쌍
info = {'name': 'Alice', 'age': 28, 'city': 'Jeonju'}
print(list(info.items()))
[('name', 'Alice'), ('age', 28), ('city', 'Jeonju')]
# 키를 이용한 값 조회
info = {'name': 'Alice', 'age': 28, 'city': 'Jeonju'}
print(info.get('name'))
print(info.get('email'))
Alice
None
# 특정 키 찾기
info = {'name': 'Alice', 'age': 28, 'city': 'Jeonju'}
print('age' in info)
print('email' in info)
True
False


3.5.3.2. 딕셔너리 추가/삭제

함수 설명
update() 다른 딕셔너리나 키워드 인수를 이용하여 원소를 추가 및 수정
pop() 특정 키의 값을 삭제하고 그 값을 반환하며, 키가 없으면 오류 발생
popitem() 마지막 (키, 값) 쌍을 삭제하고 반환
del 키워드 특정 키의 원소를 삭제하며, 키가 없으면 오류 발생
clear() 딕셔너리의 모든 원소를 삭제
# 원소 추가 및 수정1
info = {'name': 'Alice', 'age': 28}
info.update({'age': 29, 'city': 'Jeonju'})
print(info)
{'name': 'Alice', 'age': 29, 'city': 'Jeonju'}
# 원소 추가 및 수정2
info = {'name': 'Alice', 'age': 28}
info.update(age=29, city='Jeonju')
print(info)
{'name': 'Alice', 'age': 29, 'city': 'Jeonju'}
# 특정 키의 값 삭제1
info = {'name': 'Alice', 'age': 28, 'city': 'Jeonju'}
age = info.pop('age')
print(info)
print(age)
{'name': 'Alice', 'city': 'Jeonju'}
28
# 특정 키의 값 삭제2
#info = {'name': 'Alice', 'age': 28, 'city': 'Jeonju'}
#age = info.pop('email')
#print(info)
#print(email)
# 마지막 (키, 값) 쌍 삭제
info = {'name': 'Alice', 'age': 28, 'city': 'Jeonju'}
last_item = info.popitem()
print(info)
print(last_item)
{'name': 'Alice', 'age': 28}
('city', 'Jeonju')
# 특정 키의 원소 삭제1
info = {'name': 'Alice', 'age': 28, 'city': 'Jeonju'}
del info['age']
print(info)
{'name': 'Alice', 'city': 'Jeonju'}
# 특정 키의 원소 삭제2
#info = {'name': 'Alice', 'age': 28, 'city': 'Jeonju'}
#del info['email']
#print(info)


3.5.4. 딕셔너리 패킹과 언패킹

3.5.4.1. 패킹과 언패킹 개념

  • 패킹(packing) : 여러 개의 키-값 쌍을 하나의 딕셔너리로 묶어 할당하는 것
  • 언패킹(unpacking) : 하나의 딕셔너리에 묶인 키-값 쌍을 개별 변수에 분리하여 할당하는 것
# 딕셔너리 패킹
dct = {'a': 1, 'b': 2, 'c': 3}
print(dct)
{'a': 1, 'b': 2, 'c': 3}
# 딕셔너리 언패킹
d = {'a': 1, 'b': 2, 'c': 3}
a, b, c = d.values()
print(a)
print(b)
print(c)
1
2
3


3.5.4.2. 함수의 인수에서 패킹과 언패킹

  • 딕셔너리를 이용하여 함수의 키워드 가변 인수(keyword variable-length arguments)를 처리할 수 있음
  • **를 사용하여 딕셔너리를 언패킹하면, 각 키-쌍이 함수의 키워드 인수로 전달됨
# 키워드 가변 인수와 패킹, 언패킹
def print_info(**kwargs):
    for key, value in kwargs.items():                       # 전달된 값이 딕셔너리로 패킹됨
        print(f"{key}: {value}")

info = {'name': 'Alice', 'age': 28, 'city': 'Jeonju'}
print_info(**info)                                          # 딕셔너리를 언패킹하여 함수에 전달
name: Alice
age: 28
city: Jeonju


3.5.5. 딕셔너리 컴프리헨션

{키식: 값식 for 변수 in 반복범위 if 조건식}

  • 리스트 컴프리헨션과 문법이 유사하지만, 키:값 형태로 표현
# 문자 개수 세기
word = "Hello"
char_count = {char: word.count(char) for char in word}
print(char_count)
{'H': 1, 'e': 1, 'l': 2, 'o': 1}
# 두 리스트를 키와 값으로 합치기
keys = ['name', 'age', 'city']
values = ['Alice', 28, 'Jeonju']
info = {k: v for k, v in zip(keys, values)}
print(info)
{'name': 'Alice', 'age': 28, 'city': 'Jeonju'}
# 리스트를 인덱스와 함께 딕셔너리로 변환
fruits = ['apple', 'banana', 'cherry']
dct = {i: fruit for i, fruit in enumerate(fruits)}
print(dct)
{0: 'apple', 1: 'banana', 2: 'cherry'}
# 점수(값) 80 이상만 필터링
scores = {'Alice': 85, 'Bob': 92, 'Charlie': 77, 'David': 90}
passed = {name: score for name, score in scores.items() if score >= 80}
print(passed)
{'Alice': 85, 'Bob': 92, 'David': 90}
# 가격(값)에 5% 할인 적용
prices = {'apple': 1000, 'banana': 800, 'cherry': 1500}
discounted_prices = {item: price * 0.95 for item, price in prices.items()}
print(discounted_prices)
{'apple': 950.0, 'banana': 760.0, 'cherry': 1425.0}