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

이번에는 딕셔너리 안에서 딕셔너리를 사용하는 중첩 딕셔너리를 알아보겠습니다. 다음과 같이 딕셔너리는 값 부분에 다시 딕셔너리가 계속 들어갈 수 있습니다.

  • 딕셔너리 = {키1: {키A: 값A}, 키2: {키B: 값B}}

예를 들어 지구형 행성의 반지름, 질량, 공전주기를 딕셔너리로 표현해보겠습니다.

dict_dict.py

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'가 들어있고, 이 키들은 다시 값 부분에 딕셔너리를 가지고 있습니다. 즉, 중첩 딕셔너리는 계층형 데이터를 저장할 때 유용합니다.

딕셔너리 안에 들어있는 딕셔너리에 접근하려면 딕셔너리 뒤에 [ ](대괄호)를 단계만큼 붙이고 키를 지정해주면 됩니다.

  • 딕셔너리[키][키]
  • 딕셔너리[키][키] = 값

여기서는 딕셔너리가 두 단계로 구성되어 있으므로 대괄호를 두 번 사용합니다. 그래서 금성(Venus)의 반지름(mean radius)를 출력하려면 다음과 같이 먼저 'Venus'를 찾아가고 다시 'mean_radius'의 값을 가져오면 됩니다.

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

25.1 딕셔너리의 할당과 복사

리스트와 마찬가지로 딕셔너리도 할당과 복사는 큰 차이점이 있습니다. 먼저 딕셔너리를 만든 뒤 다른 변수에 할당합니다.

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

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

xyis 연산자로 비교해보면 True가 나옵니다. 즉, 변수 이름만 다를 뿐 딕셔너리 xy는 같은 객체입니다.

>>> x is y
True

xy는 같으므로 y['a'] = 99와 같이 키 'a'의 값을 변경하면 딕셔너리 xy에 모두 반영됩니다.

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

딕셔너리 xy를 완전히 두 개로 만들려면 copy 메서드로 모든 키-값 쌍을 복사해야 합니다.

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

이제 xyis 연산자로 비교해보면 False가 나옵니다. 즉, 두 딕셔너리는 다른 객체입니다. 그러나 복사한 키-값 쌍은 같으므로 ==로 비교하면 True가 나옵니다.

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

딕셔너리 xy는 별개이므로 한쪽의 값을 변경해도 다른 딕셔너리에 영향을 미치지 않습니다. 다음과 같이 딕셔너리 y에서 키 'a'의 값을 변경하면 딕셔너리 x는 그대로이고 딕셔너리 y만 바뀝니다.

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

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

그럼 딕셔너리 안에 딕셔너리가 들어있는 중첩 딕셔너리도 copy 메서드로 복사하면 될까요? 다음과 같이 중첩 딕셔너리를 만든 뒤 copy 메서드로 복사합니다.

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

이제 y['a']['python'] = '2.7.15'와 같이 y의 값을 변경해보면 xy에 모두 반영됩니다.

>>> 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 메서드 대신 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'}}

이제 딕셔너리 y의 값을 변경해도 딕셔너리 x에는 영향을 미치지 않습니다. copy.deepcopy 함수는 중첩된 딕셔너리에 들어있는 모든 딕셔너리를 복사하는 깊은 복사(deep copy)를 해줍니다.

지금까지 딕셔너리의 다양한 메서드와 응용 방법을 배웠는데, 내용이 다소 어려웠습니다. 딕셔너리의 메서드는 모두 외우지 않아도 되며 파이썬을 사용하다 보면 자연스럽게 익히게 됩니다. 여기서는 딕셔너리에 반복문을 사용하는 방법이 중요합니다. 다른 부분은 필요할 때 다시 돌아와서 찾아보세요.