Python Basic 11 | 딕셔너리 응용하기

딕셔너리에 키-값 쌍 추가

x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
x.setdefault('e')  # 'e':None 지정
print(x)  # {'a': 10, 'b': 20, 'c': 30, 'd': 40, 'e': None}
x.setdefault('f', 100)  # 'f':100 지정
print(x)  # {'a': 10, 'b': 20, 'c': 30, 'd': 40, 'e': None, 'f': 100}

딕셔너리에서 키의 값 수정

# 키가 문자열인 경우
x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
x.update(a=50)
print(x)  # {'a': 50, 'b': 20, 'c': 30, 'd': 40}
x.update(e=60)  # 없는 키를 추가하는 경우 키-값 쌍이 추가된다.
print(x)  # {'a': 50, 'b': 20, 'c': 30, 'd': 40, 'e': 60}
x.update(b=100, c=200)
print(x)  # {'a': 50, 'b': 100, 'c': 200, 'd': 40, 'e': 60}

# 키가 숫자인 경우 
y = {1: 'a', 2: 'b', 3: 'c'}
y.update({1: 'A', 2: 'B', 4: 'D'})  # 키가 숫자인 경우 딕셔너리에 넣어서 값 수정(추가)
print(y)  # {1: 'A', 2: 'B', 3: 'c', 4: 'D'}
y.update([[2, 'BB'], [4, 'DD']])  # [[키1, 값1], [키2, 값2]] 으로 수정
print(y)  # {1: 'A', 2: 'BB', 3: 'c', 4: 'DD'}
y.update(zip([1, 2], ['a', 'b']))  # zip([키1, 키2], [값1, 값2])
print(y)  # {1: 'a', 2: 'b', 3: 'c', 4: 'DD'}

setdefault와 update의 차이

setdefault는 키-값 쌍 추가만 할 수 있고, 원래 들어있던 키의 값을 수정할 수 없다.

update는 키-값 쌍 추가와 값 수정이 모두 가능하다.

딕셔너리에서 키-값 쌍 삭제

x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
deleted = x.pop('a')  # 키-값을 삭제한 후 삭제된 값을 반환한다.
print(deleted)  # 10
print(x)  # {'b': 20, 'c': 30, 'd': 40}
deleted = x.pop('z', 'none')  # (키, 기본값) 처럼 기본값을 지정하면 키가 있을 때는 삭제한 값을, 키가 없을 때는 기본값을 반환한다.
print(deleted)  # none

del x['b']  # []에 키를 지정한 후 del을 사용해 삭제한다. 
print(x)  # {'c': 30, 'd': 40}
x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
deleted = x.popitem()  # 마지막 키-값 쌍을 삭제하여 삭제한 키-값 쌍을 튜플로 반환한다. (python 3.6)
print(deleted)  # ('d', 40)
print(x)  # {'a': 10, 'b': 20, 'c': 30}
x.clear()  # 모든 키-값 쌍 삭제 
print(x)  # {}

딕셔너리에서 키의 값 가져오기

x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
print(x.get('a'))  # 10
print(x.get('z', 'none'))  # none, 기본값을 지정하면 키가 없을 때는 기본값 반환 

딕셔너리에서 키-값 모두 가져오기

x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
print(x.items())  # 딕셔너리의 키-값 쌍 모두 가져오기
print(x.keys())  # 딕셔너리의 키 모두 가져오기
print(x.values())  # 딕셔너리의 값 모두 가져오기

# 결과 
dict_items([('a', 10), ('b', 20), ('c', 30), ('d', 40)])
dict_keys(['a', 'b', 'c', 'd'])
dict_values([10, 20, 30, 40])

리스트와 튜플로 딕셔너리 만들기

keys = ['a', 'b', 'c', 'd']
x = dict.fromkeys(keys)
print(x)  # {'a': None, 'b': None, 'c': None, 'd': None}
y = dict.fromkeys(keys, 100)
print(y)  # {'a': 100, 'b': 100, 'c': 100, 'd': 100}

defaultdict 사용하기

from collections import defaultdict
x = defaultdict(int)
print(x)  # defaultdict(<class 'int'>, {})
print(x['z'])  # 0

x 에는 키 'z'가 없지만 키의 값을 가져오면 0이 나온다. default( )int (int() 는 기본값으로 0을 반환)를 넣었기 때문이다.

from collections import defaultdict
x = defaultdict(lambda: 'python')  
print(x['y'])  # python

기본값을 바꾸려면 python을 반환하는 람다 함수를 기본값 생성 함수로 만들어서 넣어준다.

반복문으로 키-값 출력하기

x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
# 키만 출력
for i in x:
    print(i, end=' ')
# a b c d

# 키, 값 모두 출력 
for key, val in x.items():
    print(key, val)
# a 10
# b 20
# c 30
# d 40

# 키만 출력 
for key in x.keys():
    print(key, end=' ')
# a b c d

# 값만 출력 
for val in x.values():
    print(val, end=' ')
# 10 20 30 40

딕셔너리 표현식 사용하기

  • {키: 값 for 키, 값 in 딕셔너리}
  • dict({키: 값 for 키, 값 in 딕셔너리})
keys = ['a', 'b', 'c', 'd']
x = {key: val for key, val in dict.fromkeys(keys).items()}
print(x)  # {'a': None, 'b': None, 'c': None, 'd': None}
y = {key: val for key, val in dict.fromkeys(keys, 100).items()}
print(y)  # {'a': 100, 'b': 100, 'c': 100, 'd': 100}

keys = ['a', 'b', 'c', 'd']
dic = {'a': 1, 'b': 2, 'c': 3, 'd': 4}

# 키만 가져온 뒤 값으로 0 넣기 
x = {key: 0 for key in dict.fromkeys(keys).keys()}
print(x)  # {'a': 0, 'b': 0, 'c': 0, 'd': 0}

# 값을 가져온 뒤 값을 키로 사용
y = {val: 0 for val in dic.values()}
print(y)  # {1: 0, 2: 0, 3: 0, 4: 0}

# 키: 값 자리 바꾸기
dic = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
x = {val: key for key, val in dic.items()}
print(x)  # {1: 'a', 2: 'b', 3: 'c', 4: 'd'}

표현식이 유용한 경우 : 딕셔너리에서 특정 값을 찾아서 삭제할 때

if 조건문을 지정하면 삭제할 키-값 쌍을 제외하고 남은 값으로 새 딕셔너리를 만든다.

dic = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
dic = {key: val for key, val in dic.items() if val != 4}
print(dic)  # {'a': 1, 'b': 2, 'c': 3}

중첩 리스트

student_info = {
    'hyerin': {
        'phone': '010-1111-1111',
        'age': 26
    },
    'mizu': {
        'phone': '010-2222-2222',
        'age': 28
    },
    'jenny': {
        'phone': '010-3333-3333',
        'age': 27
    }
}

# 중첩 리스트에 접근하기: 딕셔너리[키][키]
print(student_info['jenny']['phone'])  # 010-3333-3333

딕셔너리 복사하기

x = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
y = x.copy()
print(x is y)  # False
print(x == y)  # True
y['a'] = 10
print(x)  # {'a': 1, 'b': 2, 'c': 3, 'd': 4}
print(y)  # {'a': 10, 'b': 2, 'c': 3, 'd': 4}

copy 메소드로 복사하면 x와 y 는 다른 객체가 되어 x is y 는 False 가 되지만, 키-값 쌍은 전부 같기 때문에 == 로 비교하면 True이다.

별개의 객체이기 때문에 한 쪽을 변경해도 다른 쪽이 영향을 받지 않는다.

중첩 딕셔너리 복사하기

그냥 copy를 사용한 경우

student_info = {
    'hyerin': {
        'phone': '010-1111-1111',
        'age': 26
    },
    'mizu': {
        'phone': '010-2222-2222',
        'age': 28
    },
    'jenny': {
        'phone': '010-3333-3333',
        'age': 27
    }
}
student_info_copy = student_info.copy()
print(student_info is student_info_copy)
student_info_copy['hyerin']['age'] = 27
print(student_info_copy)  # 원본과 복사본 모두에 변경사항이 반영된다. 
print(student_info)

copy 모듈의 deepcopy 함수를 사용한 경우

import copy

student_info = {
    'hyerin': {
        'phone': '010-1111-1111',
        'age': 26
    },
    'mizu': {
        'phone': '010-2222-2222',
        'age': 28
    },
    'jenny': {
        'phone': '010-3333-3333',
        'age': 27
    }
}
student_info_copy = copy.deepcopy(student_info)
student_info_copy['hyerin']['age'] = 27
print(student_info_copy)  # 원본은 그대로, 복사본에만 변경 내용이 반영된다. 
print(student_info)

딕셔너리 병합하기

# update 이용 
x = {'a': 1, 'b': 2}
y = {'c': 3, 'd': 4}
x.update(y)
print(x)  # {'a': 1, 'b': 2, 'c': 3, 'd': 4}

# 딕셔너리 언패킹 이용 (파이썬 3.5 부터)
x = {'a': 1, 'b': 2}
y = {'c': 3, 'd': 4}
print({**x, **y})  # {'a': 1, 'b': 2, 'c': 3, 'd': 4}

좋은 웹페이지 즐겨찾기