파이썬 | 딕셔너리 응용하기

CHOI·2021년 11월 19일
1

Python

목록 보기
18/33
post-thumbnail

1. 딕셔너리 조작하기

키-값 쌍 추가하기

키-값 을 추가하는 메서드는 다음과 같이 두 가지가 있다.

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

setdefault

>>> x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
>>> x.setdefault('e')
>>> x
{'a': 10, 'b': 20, 'c': 30, 'd': 40, 'e': None}

setdefault(키) 를 하면 키가 추가되고 값에는 None 이 들어간다.

>>> x.setdefault('f', 100)
100
>>> x
{'a': 10, 'b': 20, 'c': 30, 'd': 40, 'e': None, 'f': 100}

setdefault(키, 값) 을 해주면 키와 값이 추가가 된다.

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(a=900, e=50)
>>> x
{'a': 900, 'b': 20, 'c': 30, 'd': 40, 'e': 50}

위와 같이 해당 키가 없으면 추가하게 된다. 또한 콤마를 통해서 수정도 같이 한 번에 할 수 있다.

>>> 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'}

다른 방법으로 리스트나 튜플을 이용하는 방법도 있고

>>> y.update(zip([1, 2], ['one', 'two']))
>>> y
{1: 'one', 2: 'two', 3: 'THREE', 4: 'FOUR'}

zip 객체로 값을 수정할 수도 있다.

setdefault와 update의 차이점은 setdefault는 '추가'만 가능하고 '수정'은 불가능하다.

키-값 쌍 삭제하기 (pop, del)

>>> x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
>>> x.pop('a')
10
>>> x
{'b': 20, 'c': 30, 'd': 40}

pop 을 사용하여 삭제할 수 있다.

>>> x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
>>> del x['a']
>>> x
{'b': 20, 'c': 30, 'd': 40}

del 을 사용하여 삭제할 수 있는데 [ ] 안에 키 값을 입력해야한다.

맨 마지막 키-값 쌍 삭제하기 (popitem)

>>> x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
>>> x.popitem()
('d', 40)
>>> x
{'a': 10, 'b': 20, 'c': 30}

파이썬 3.6 이상에서는 popitem 은 마지막 키-값 쌍이 삭제되고 그 이전 버전은 임의의 쌍이 삭제된다.

모든 키-값 쌍 삭제하기 (clear)

>>> x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
>>> x.clear()
>>> x
{}

키의 값 가져오기 (get)

>>> x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
>>> x.get('a')
10

키-값 쌍 모두 가져오는 메서드 (item, keys, values)

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

리스트나 튜플로 딕셔너리 만들기 (fromkeys)

이번에는 리스트(튜플)로 딕셔너리를 만들어보자.

먼저 keys = ['a', 'b', 'c', 'd'] 와 같이 키가 들어있는 리스트를 준비하고 dict.fromkeys 에 키가 들어있는 리스트를 넣어주면 된다.

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

그러면 키 리스트로 딕셔너리가 생성되고 값은 모두 None 으로 저장된다.

>>> y = dict.fromkeys(keys, 100)
>>> y
{'a': 100, 'b': 100, 'c': 100, 'd': 100}

dict.fromkeys(keys, 100) 와 같이 키 리스트와 값을 지정하면 해당 값이 키의 값으로 저장된다.

2. 반복문으로 딕셔너리 키-값 출력 (items)

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

for i in x: 처럼 반복문에 딕셔너리를 지정한 뒤에 i 를 출력해보면 값은 출력되지 않고 키만 출력이 된다.

그렇다면 키와 값 둘다 출력하려면 어떻게 해야할까?

>>> 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

다음과 같이 item 메서드를 사용하면 변수 두 개의 각각 키와 값이 들어가게 된다.

키만 or 값만 출력하기

지금까지 item 을 활용하여 키와 값 모두 가져왔는데 keysvalues 를 이용하여 키만 가져오거나 값만 가져올 수 있다.

>>> x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
>>> for key in x.keys():
...     print(key, end=' ')
...
a b c d
>>> x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
>>> for value in x.values():
...     print(value, end=' ')
...
10 20 30 40

3. 딕셔너리 표현식 사용하기

  • {키: 값 for 키, 값 in 딕셔너리}
  • dict({키: 값 for 키, 값 in 딕셔너리})

리스트와 마찬가지로 for 문과 if 조건문을 사용하여 딕셔너리를 만들어보자.

>>> 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 를 사용하여 반복문에서 keyvalue 를 가져와서 딕셔너리를 만들었다.

Untitled

>>> {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'}

또는 위와 같이 키와 값을 바꾸는 등의 활용도 할 수 있다.

딕셔너리 표현식에서 if 문 사용

근데 딕셔너리 표현식을 사용하면 복잡하기만하고 dict.fromkeys 와 큰 차이점이 없다. 대신 딕셔너리 표현식은 특정 값을 찾아네서 삭제할 때 유용하다.

딕셔너리는 특정 값을 삭제하는 pop 메서드만 제공하고 특정 값을 삭제하는 메서드는 제공되지 않는다. 그러면 특정 값을 어떻게 삭제시킬 수 있을까? 아마도 반복문을 통해서 값을 가져와서 일일히 확인한 다음에 삭제하는 방법을 떠올릴 수 있을 것이다.

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 조건문을 사용하여 삭제할 값을 제외시키면 된다.

>>> 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}

이와 같은 방법이 가능한 이유는 이는 특정 값을 삭제하는 것이 아니라 딕셔너리 표현식을 사용하여 조건에 만족하는 값들로만 새로운 딕셔너리를 만드는 것이기 때문이다.

Untitled

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

딕셔너리 terrestrial_planet 는 키 'Mercury', 'Venus', 'Earth', 'Mars' 가 있고 각 키의 값으로 딕셔너리를 가지고 있는 것이다. 딕셔너리 안에 딕셔너리에 접근하기 위해서는 딕셔너리 뒤에 [ ]대괄호 를 단계만큼 들어가고 키를 붙여서 지정해주면 된다.

말이 복잡해서 이해하기 조금 어려울 수 있는데 단순하게 지금은 딕셔너리 안에 딕셔너리 총 2 단계니까 대괄호를 두번 쓰면 키값에 접근할 수 있다.

print(terrestrial_planet['Venus']['mean_radius'])    # 6051.8

5. 딕셔너리 할당과 복사

딕셔너리 복사 (copy)

리스트와 마찬가지로 딕셔너리도 할당과 복사에는 큰 차이점이 있다.

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

위와 같이 먼저 딕셔너리를 만든뒤에 다른 변수에 할당하자. 그러면 이는 딕셔너리가 두 개가 된 것 같지만 실제로는 한 개의 딕셔너리이다.

>>> x is y
True

실제로 is 연산자로 확인해보면 둘이 같다는 것을 볼 수 있다.

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

따라서 y 변수에서 값을 변경하고 x 를 출력해보면 값이 바뀐것을 볼 수 있다.

그렇다면 완전히 두 개의 딕셔너리를 만들려면 어떻게 해야할까?

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

copy() 를 사용하면 된다.

>>> x is y
False
>>> x == y
True

그러면 값만 같고 서로 별개인 딕셔너리 두 개가 생성이 된다.

중첩 딕셔너리 복사 (deepcopy)

딕셔너리 안에 딕셔너리가 있는 중첩 딕셔너리도 copy 를 사용하면 될까? 실제로 확인해보자.

>>> x = {'a': {'python': '2.7'}, 'b': {'python': '3.6'}}
>>> y = x.copy()

먼저 복사 한 다음에

>>> 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'}}

값을 변경하고 확인해보면 둘 다 바뀐 것을 볼 수 있다. 이를 해결하기 위해선 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'}}

이러면 우리가 서로 별 개의 중첩 리스트 두 개가 만들어진다.

profile
벨로그보단 티스토리를 사용합니다! https://flight-developer-stroy.tistory.com/

0개의 댓글