키-값 을 추가하는 메서드는 다음과 같이 두 가지가 있다.
>>> 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(키, 값)
을 해주면 키와 값이 추가가 된다.
이번에는 키-값을 수정하면서 추가도 가능한 메서드를 보자
>>> 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는 '추가'만 가능하고 '수정'은 불가능하다.
>>> 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 을 사용하여 삭제할 수 있는데 [ ] 안에 키 값을 입력해야한다.
>>> x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
>>> x.popitem()
('d', 40)
>>> x
{'a': 10, 'b': 20, 'c': 30}
파이썬 3.6 이상에서는 popitem
은 마지막 키-값 쌍이 삭제되고 그 이전 버전은 임의의 쌍이 삭제된다.
>>> x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
>>> x.clear()
>>> x
{}
>>> x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
>>> x.get('a')
10
>>> 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])
이번에는 리스트(튜플)로 딕셔너리를 만들어보자.
먼저 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)
와 같이 키 리스트와 값을 지정하면 해당 값이 키의 값으로 저장된다.
>>> 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
메서드를 사용하면 변수 두 개의 각각 키와 값이 들어가게 된다.
지금까지 item
을 활용하여 키와 값 모두 가져왔는데 keys
나 values
를 이용하여 키만 가져오거나 값만 가져올 수 있다.
>>> 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
{키: 값 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
를 사용하여 반복문에서 key
와 value
를 가져와서 딕셔너리를 만들었다.
>>> {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'}
또는 위와 같이 키와 값을 바꾸는 등의 활용도 할 수 있다.
근데 딕셔너리 표현식을 사용하면 복잡하기만하고 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}
이와 같은 방법이 가능한 이유는 이는 특정 값을 삭제하는 것이 아니라 딕셔너리 표현식을 사용하여 조건에 만족하는 값들로만 새로운 딕셔너리를 만드는 것이기 때문이다.
딕셔너리 = {키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
리스트와 마찬가지로 딕셔너리도 할당과 복사에는 큰 차이점이 있다.
>>> 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
그러면 값만 같고 서로 별개인 딕셔너리 두 개가 생성이 된다.
딕셔너리 안에 딕셔너리가 있는 중첩 딕셔너리도 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'}}
이러면 우리가 서로 별 개의 중첩 리스트 두 개가 만들어진다.