코딩도장_Unit 25. 딕셔너리 응용하기

김민주·2022년 1월 1일
1

AIFFEL_풀잎스쿨

목록 보기
21/23
post-thumbnail

25.1 딕셔너리 조작하기

25.1.1 딕셔너리에 키-값 쌍 추가하기

딕셔너리에 키-값 쌍을 추가하는 메서드 2가지

  • setdefault: 키-값 쌍 추가
  • update: 키의 값 수정, 키가 없으면 키-값 쌍 추가

25.1.2 딕셔너리에 키와 기본값 저장하기

  • setdefault(키)
    • setdefault에 키만 지정하면 값에 None을 저장
>>> x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
>>> x.setdefault('e')
>>> x
{'a': 10, 'b': 20, 'c': 30, 'd': 40, 'e': None}
  • setdefault(키, 기본값)
    • 키와 기본값을 지정하면 값에 기본값을 저장한 뒤 해당 값을 반환
>>> x = {'a': 10, 'b': 20, 'c': 30, 'd': 40, 'e': None}
>>> x.setdefault('f', 100)
100
>>> x
{'a': 10, 'b': 20, 'c': 30, 'd': 40, 'e': None, 'f': 100}

25.1.3 딕셔너리에서 키의 값 수정하기

  • update(키=값)
    • 딕셔너리에서 키의 값 수정
    • 키와 값을 넣어줄 때 작은따옴표, 큰따옴표 생략
    • 딕셔너리에 키가 없으면 키-값 쌍 추가
    • 키-값 쌍 여러 개를 콤마로 구분해서 넣으면 값을 한꺼번에 수정
    • 키가 문자열일 때만 사용 가능
    • 키가 숫자일 경우에는 update(딕셔너리)처럼 딕셔너리를 넣어서 값 수정
    • update(리스트), update(튜플)은 리스트와 튜플로 값 수정
      (리스트는 [[키1, 값1], [키2, 값2]] 형식으로 키와 값을 리스트로 만든다.(튜플도 동일))
    • update(반복가능한객체)는 키-값 쌍으로 된 반복 가능한 객체로 값 수정🔎
>>> x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
>>> x.update(a=90)  # 작은따옴표, 큰따옴표 생략
>>> x
{'a': 90, 'b': 20, 'c': 30, 'd': 40}

# 키-값 쌍 추가
>>> x.update(e=50)
>>> x
{'a': 90, 'b': 20, 'c': 30, 'd': 40, 'e': 50}

# 값 한꺼번에 수정
>>> x.update(a=900, f=60)
>>> x
{'a': 900, 'b': 20, 'c': 30, 'd': 40, 'e': 50, 'f': 60}

# 딕셔너리를 사용해 숫자 넣기
>>> y = {1: 'one', 2: 'two'}
>>> y.update({1: 'ONE', 3: 'THREE'})
>>> y
{1: 'ONE', 2: 'two', 3: 'THREE'}

# update(리스트)
>>> y.update([[2, 'TWO'], [4, 'FOUR']])
>>> y
{1: 'ONE', 2: 'TWO', 3: 'THREE', 4: 'FOUR'}

# update(반복가능한객체)
>>> y.update(zip([1, 2], ['one', 'two']))
>>> y
{1: 'one', 2: 'two', 3: 'THREE', 4: 'FOUR'}

📎 참고) setdefault와 update의 차이

  • setdefault: 키-값 쌍 추가만 할 수 있고, 이미 들어있는 키의 값은 수정 불가능
  • update: 키-값 쌍 추가와 값 수정 모두 가능
>> x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
>> x.setdefault('a', 90)
10
>> x   # 값 수정 불가능
{'a': 10, 'b': 20, 'c': 30, 'd': 40}

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

  • pop(키)
    • 딕셔너리에서 특정 키-값 쌍을 삭제한 뒤 삭제한 값 반환
>>> x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
>>> x.pop('a')
10
>>> x
{'b': 20, 'c': 30, 'd': 40}
  • pop(키, 기본값)
    • 기본값을 지정하면 딕셔너리에 키가 있을 때는 해당 키-값 쌍을 삭제한 뒤 삭제한 값을 반환
    • 키가 없을 때는 기본값만 반환
>>> x.pop('z', 0)  # 딕셔너리에 키가 없으므로 기본값으로 지정한 0 반환
0
  • del
    • [ ]에 키를 지정하여 특정 키-값 쌍을 삭제
>>> x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
>>> del x['a']
>>> x
{'b': 20, 'c': 30, 'd': 40}

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

  • popitem()
    • 딕셔너리에서 임의의(파이썬 3.5이하), 마지막(파이썬 3.6이상) 키-값 쌍을 삭제한 뒤 삭제한 값 반환
#파이썬 3.6이상 : 마지막 키-값 쌍 삭제 뒤 반환
>>> x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
>>> x.popitem()
('d', 40)
>>> x
{'a': 10, 'b': 20, 'c': 30}

#파이썬 3.5 이하 : 임의의 키-값 쌍 삭제 뒤 반환, 매번 삭제하는 키-값 쌍이 달라짐

25.1.6 딕셔너리의 모든 키-값 쌍을 삭제하기

  • clear()
    • 딕셔너리의 모든 키-값 쌍 삭제
>>> x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
>>> x.clear()
>>> x
{}

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

  • get(키)
    • 딕셔너리에서 특정 키의 값을 가져온다.
>>> x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
>>> x.get('a')
10
  • get(키, 기본값)
    • 기본값을 지정하면 딕셔너리에 키가 있을 때는 해당 키의 값 반환
    • 키가 없을 때는 기본값 반환
>>> x.get('z', 0)  # z라는 키가 없어 지정했던 기본값 0 출력
0

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

  • items() : 키-값 쌍을 모두 가져옴
>>> x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
>>> x.items()
dict_items([('a', 10), ('b', 20), ('c', 30), ('d', 40)])
  • keys() : 키를 모두 가져옴
>>> x.keys()
dict_keys(['a', 'b', 'c', 'd'])
  • values() : 값을 모두 가져옴
>>> x.values()
dict_values([10, 20, 30, 40])

위 메서드들은 보통 for 반복문과 조합해서 사용

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

  • dict.fromkeys(키리스트)
    • 키 리스트로 딕셔너리를 생성하며 값은 모두 None으로 저장
>>> keys = ['a', 'b', 'c', 'd']  # 먼저 키가 들어있는 리스트 준비(튜플도 가능)
>>> x = dict.fromkeys(keys)
>>> x
{'a': None, 'b': None, 'c': None, 'd': None}
  • dict.fromkeys(키리스트, 값)
    • 키 리스트와 값을 지정하면 해당 값이 키의 값으로 저장
>>> keys = ['a', 'b', 'c', 'd'] 
>>> y = dict.fromkeys(keys, 100)
>>> y
{'a': 100, 'b': 100, 'c': 100, 'd': 100}

📎 참고) defaultdict 사용하기
위에서 사용한 딕셔너리(dict)는 없는 키에 접근했을 경우 에러가 발생

>> x = {'a': 0, 'b': 0, 'c': 0, 'd': 0}
>> x['z']    # 키 'z'는 없음
Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    x['z']
KeyError: 'z'

이때는 defaultdict를 사용

  • defaultdict(기본값생성함수)
    • 없는 키에 접근하더라도 에러가 발생하지 않으며 기본값을 반환
    • collections 모듈에 들어있으며 기본값 생성 함수를 넣는다.
>> from collections import defaultdict    # collections 모듈에서 defaultdict를 가져옴
>> y = defaultdict(int)    # int로 기본값 생성

기본값을 0으로 설정했기 때문에 키의 값을 가져와보면 0이 나온다.

>> y['z']
0

int를 넣었는데 기본값이 0인 이유는

>> int()
0          # int에 아무것도 넣지 않고 호출하면 0 반환

0이 아닌 다른 값을 기본값으로 설정하고 싶다면 기본값 생성 함수를 만들어서 넣으면 된다.

>> z = defaultdict(lambda: 'python')
>> z['a']
'python'
>> z[0]
'python'

25.2 반복문으로 딕셔너리의 키-값 쌍을 모두 출력하기

for i in x:처럼 for 반복문에 딕셔너리를 지정한 뒤에 print로 변수 i를 출력해보면 키만 출력된다.

>>> x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
>>> for i in x:
        print(i, end=' ')

# 실행결과
a b c d

키와 값을 모두 출력하려면 for in 뒤에 딕셔너리를 지정하고 items 사용한다.

for,in 딕셔너리.items():
     반복할 코드
>>> x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
>>> for key, value in x.items():
        print(key, value)

# 실행결과
a 10
b 20
c 30
d 40

for key, value in x.items():는 딕셔너리 x에서 키-값 쌍을 꺼내서 키는 key에 값은 value에 저장하고, 꺼낼 때마다 코드를 반복한다.
in 다음에 딕셔너리를 직접 지정하고 items를 사용해도 무방

for key, value in {'a': 10, 'b': 20, 'c': 30, 'd': 40}.items():
    print(key, value)

25.2.1 딕셔너리의 키만 출력하기

  • for 반복문에서 keys로 키만 가져오면서 반복
>>> x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
>>> for key in x.keys():
        print(key, end=' ')

# 실행결과
a b c d

25.2.1 딕셔너리의 값만 출력하기

  • for 반복문에서 values로 값만 가져오면서 반복
>>> x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
>>> for value in x.values():
        print(value, end=' ')

# 실행결과
10 20 30 40

25.3 딕셔너리 표현식 사용하기

딕셔너리도 for 반복문과 if 조건문을 사용하여 딕셔너리를 생성할 수 있다.

  • {키: 값 for 키, 값 in 딕셔너리}
  • dict({키: 값 for 키, 값 in 딕셔너리})
    • for in 다음에 딕셔너리를 지정하고 items 사용
    • 키, 값을 가져온 뒤에는 키: 값 형식으로 변수나 값을 배치하여 딕셔너리 생성
>>> keys = ['a', 'b', 'c', 'd']
>>> x = {key: value for key, value in dict.fromkeys(keys).items()}
>>> x
{'a': None, 'b': None, 'c': None, 'd': None}

dict.fromkeys(keys).items()로 키-값 쌍을 구한 뒤 키는 변수 key, 값은 변수 value에 꺼내고 최종적으로 keyvalue를 이용하여 딕셔너리를 만든다.

x = {key: value for key, value in dict.fromkeys(keys).items()}


keys로 키만 가져온 뒤 특정 값을 넣거나, values로 값을 가져온 뒤 값을 키로 사용할 수도 있다.

>>> {key: 0 for key in dict.fromkeys(['a', 'b', 'c', 'd']).keys()}               # 키만 가져옴
{'a': 0, 'b': 0, 'c': 0, 'd': 0}
>>> {value: 0 for value in {'a': 10, 'b': 20, 'c': 30, 'd': 40}.values()}        # 값을 키로 사용
{10: 0, 20: 0, 30: 0, 40: 0}

키와 값의 자리를 바꾸는 등 여러 가지로 응용 가능

>>> {value: key for key, value in {'a': 10, 'b': 20, 'c': 30, 'd': 40}.items()}  # 키-값 자리를 바꿈
{10: 'a', 20: 'b', 30: 'c', 40: 'd'}

25.3.1 딕셔너리 표현식에서 if 조건문 사용하기

  • 딕셔너리 표현식은 딕셔너리에서 특정 값을 찾아서 삭제할 때 유용
  • for 반복문으로 반복하면서 del로 삭제
x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
 
for key, value in x.items():
    if value == 20:    # 값이 20이면
        del x[key]     # 키-값 쌍 삭제
 
print(x)
# 실행결과
Traceback (most recent call last):
  File "C:\project\dict_del_by_value_error.py", line 3, in <module>
    for key, value in x.items():
RuntimeError: dictionary changed size during iteration 

딕셔너리의 크기가 바뀌었다는 에러 발생. 즉, 딕셔너리는 for 반복문으로 반복하면서 키-값 쌍을 삭제하면 안 된다.

  • 딕셔너리 표현식에서 if조건문을 사용하여 삭제할 값 제외
    • {키: 값 for 키, 값 in 딕셔너리 if 조건식}
    • dict({키: 값 for 키, 값 in 딕셔너리 if 조건식})
>>> x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
>>> x = {key: value for key, value in x.items() if value != 20}
>>> x
{'a': 10, 'c': 30, 'd': 40}

직접 키-값 쌍을 삭제하는 방식이 아니라 삭제할 키-값 쌍을 제외하고 남은 키-값 쌍으로 딕셔너리를 새로 만드는 방식

25.4 딕셔너리 안에서 딕셔너리 사용하기

  • 딕셔너리는 값 부분에 다시 딕셔너리가 계속 들어갈 수 있다.
    (중첩 딕셔너리)
    • 딕셔너리 = {키1: {키A: 값A}, 키2: {키B: 값B}}
terrestrial_planet = {
    'Mercury': {
        'mean_radius': 2439.7,
        'mass': 3.3022E+23,
        'orbital_period': 87.969
    },
    'Venus': {
        'mean_radius': 6051.8,
        'mass': 4.8676E+24,
        'orbital_period': 224.70069,
    },
    'Earth': {
        'mean_radius': 6371.0,
        'mass': 5.97219E+24,
        'orbital_period': 365.25641,
    },
    'Mars': {
        'mean_radius': 3389.5,
        'mass': 6.4185E+23,
        'orbital_period': 686.9600,
    }
}
 
print(terrestrial_planet['Venus']['mean_radius'])    # 6051.8
# 실행결과
6051.8

딕셔너리 terrestrial_planet에 키 'Mercury', 'Venus', 'Earth', 'Mars'가 들어있고, 이 키들은 다시 값 부분에 딕셔너리가 들어있다.

  • 중첩 딕셔너리는 계층형 데이터를 저장할 때 유용
  • 딕셔너리 안에 들어있는 딕셔너리에 접근하려면 딕셔너리 뒤에 대괄호([])를 단계만큼 붙이고 키 지정
    • 딕셔너리[키][키]
    • 딕셔너리[키][키] = 값
print(terrestrial_planet['Venus']['mean_radius']) 
# 딕셔너리가 두 단계로 구성되어 있으므로 대괄호 두 번 사용
# 6051.8

25.5 딕셔너리의 할당과 복사

>>> x = {'a': 0, 'b': 0, 'c': 0, 'd': 0}
>>> y = x

y = x와 같이 딕셔너리를 다른 변수에 할당하면 딕셔너리는 두 개가 될 것 같지만 실제로는 딕셔너리가 한 개이다.

>>> x is y
True

즉, 변수 이름만 다를 뿐 딕셔너리 x와 y는 같은 객체이다.

>>> y['a'] = 99
>>> x
{'a': 99, 'b': 0, 'c': 0, 'd': 0}
>>> y
{'a': 99, 'b': 0, 'c': 0, 'd': 0}

값을 변경하면 딕셔너리 x와 y에 모두 반영된다.

완전히 두 개로 만들려면 copy 메서드로 모든 키-값 쌍을 복사

>>> x = {'a': 0, 'b': 0, 'c': 0, 'd': 0}
>>> y = x.copy()

>>> x is y  # 서로 다른 객체
False
>>> x == y  # 키-값 쌍은 같으므로 
True

>>> y['a'] = 99
>>> x
{'a': 0, 'b': 0, 'c': 0, 'd': 0}
>>> y
{'a': 99, 'b': 0, 'c': 0, 'd': 0}  # 서로 영향을 미치지 않는다

25.5.1 중첩 딕셔너리의 할당과 복사 알아보기

  • 중첩 딕셔너리의 경우 copy메서드로 복사하면 완전히 불리가 되지 않는다.
>>> x = {'a': {'python': '2.7'}, 'b': {'python': '3.6'}}
>>> y = x.copy()

# y값 변경 시 x, y 모두 반영
>>> y['a']['python'] = '2.7.15'
>>> x
{'a': {'python': '2.7.15'}, 'b': {'python': '3.6'}}
>>> y
{'a': {'python': '2.7.15'}, 'b': {'python': '3.6'}}
  • 완전히 복사하려면 copy 모듈의 deepcopy 함수를 사용
>>> x = {'a': {'python': '2.7'}, 'b': {'python': '3.6'}}
>>> import copy             # copy 모듈을 가져옴
>>> y = copy.deepcopy(x)    # copy.deepcopy 함수를 사용하여 깊은 복사
>>> y['a']['python'] = '2.7.15'
>>> x
{'a': {'python': '2.7'}, 'b': {'python': '3.6'}}
>>> y
{'a': {'python': '2.7.15'}, 'b': {'python': '3.6'}}
  • copy.deepcopy 함수는 중첩된 딕셔너리에 들어있는 모든 딕셔너리를 복사하는 깊은 복사(deep copy)를 해준다.

25.6 연습문제: 평균 점수 구하기

다음 소스 코드를 완성하여 평균 점수가 출력되게 만드세요.

maria = {'korean': 94, 'english': 91, 'mathematics': 89, 'science': 83}
 
__________________________          
print(average)
# 실행결과
89.25
# 정답
average = sum(maria.values()) / len(maria)

여기서 평균 점수를 구하려면 딕셔너리의 값을 모두 더한 뒤 딕셔너리의 키 개수로 나눠주어야 한다.
딕셔너리에서 값을 모두 더하려면 sum(maria.values())와 같이 values로 값을 모두 가져온 뒤 sum 함수 사용
키의 개수는 len(maria)처럼 len으로 구한다.
sum으로 구한 값을 len(maria)로 나눠주면 평균을 구한다.

profile
안녕하세요 :-) 잘 부탁드립니다!

0개의 댓글