점프 투 파이썬 : https://wikidocs.net/book/1
파이썬 기본을 갈고 닦자 : https://wikidocs.net/16031
딕셔너리는 내부적으로 해시테이블로 구현되어있어, key-value 쌍으로 데이터를 저장하고 사용할 수 있다.
key
는 하나의 열쇠다. value
가 그 열쇠로 접근할 수 있는 방, 또는 물건이 되는 것이다.
즉, 여태까지는 번호로 물건을 찾았다면 이제는 이름으로 물건을 찾을 수 있다는 것이다. 때문에 딕셔너리는 순차적이지 않다. key
는 어떤 key
값을 넣냐에 따라 달라지기 때문이다.
기본적인 모습은 다음과 같다.
a = {'key' : value}
a = dict()
값으로 이거저거 다 넣을 수 있다.
a = {'list': [1,2,3], 'tuple': (1,2,3), 'number': 2 , 'string':"hello"}
print(a['list'] , a['tuple'], a['number'] , a['string']) # [1, 2, 3] (1, 2, 3) 2 hello
다음과 같이 리스트, 튜플, 정수, 문자열 이밖에 실수형, bool, 집합, 객체 등 다양한 자료형들을 넣을 수 있다.
딕셔너리는 없는 key에 값을 넣어주면 key-value를 추가할 수 있다.
a = {1 : 'a'}
a[2] = 'b'
print(a) # {1: 'a', 2: 'b'}
a에는 2
에 해당하는 key-value 쌍이 없었는데, 위와 같이 추가할 수 있다.
삭제는 list와 같이 del
을 사용한다.
a = {1 : 'a'}
a[2] = 'b'
del a[1]
print(a) # {2: 'b'}
값을 가져오는 방법도 굉장히 간단하다. key
통해 value
를 가져오면 된다.
grade = {'math' : 90}
print(grade['math']) # 90
print(grade['english']) # KeyError: 'english'
단, 없는 key값을 호출하면 error가 발생한다.
한가지 재밌는 것은 key
로 올 수 있는 것들은 immutable
한 것들이다. 즉, 불변하는 것들인데 우리가 아는 것은 숫자, 튜플, 문자열, bool 등
이 있다.
그래서 튜플과 실수도 넣을 수도 있다.
grade = {(1,2) : 3, 2.1412 : 'number'}
grade[(1,2)] = 13
print(grade[(1,2)] , grade[2.1412]) # 13 number
단, 동일한 key
로 값을 넣으면 값을 덮어쓰니 조심하도록 하자
grade = {'math': 2, 'math' : 20}
print(grade['math']) # 20
grade['math'] = 30
print(grade['math']) # 30
key들의 이름을 알고싶다면 keys()
를 사용하면 키들을
반환해준다.
grade = {'math': 2, 'english': 30, 5: 10}
print(grade.keys()) # dict_keys(['math', 'english', 5])
dict_keys
라는 요상한 값이 나오는데, 이들은 리스트는 아니더라도 기본적인 반복문을 실행할 수 있다. 그래서 다음과 같은 문법이 가능하다.
grade = {'math': 2, 'english': 30, 5: 10}
for k in grade.keys():
print(k)
#math
#english
#5
dict_keys
말고도, dict_values
, dict_items
등과 같은 객체들이 더 있다. 이들은 리스트가 아니므로 리스트 고유의 append, insert, pop, remove, sort
함수를 수행할 수 없다. 그러나 리스트처럼 iterable할 수 있으므로 for문으로 순회가 가능하다.
dict_keys, dict_values, dict_items
모두 리스트로 변환이 가능한데, 변환하려면 다음과 같이하면 된다.
grade = {'math': 2, 'english': 30, 5: 10}
print(list(grade)) # ['math', 'english', 5]
list
로 묶어내면 된다.
이번에는 value()
메서드를 사용하면 된다.
grade = {'math': 2, 'english': 30, 5: 10}
print(grade.values()) # dict_values([2, 30, 10])
위에서 key
값들을 얻어낼 때와 같이 values()
로 값을 얻어내면 dict_values
객체가 나온다. 이 역시 list
로 씌우면 리스트로 변환된다.
items()
메서드를 사용하면 key, value
쌍으로 된 튜플을 dict_items
객체로 돌려준다. 마찬가지로 dict_items
를 list
로 감싸면 list에 담기게 된다.
grade = {'math': 2, 'english': 30, 5: 10}
print(grade.items()) # dict_items([('math', 2), ('english', 30), (5, 10)])
print(list(grade.items())) # [('math', 2), ('english', 30), (5, 10)]
clear()
메서드를 사용하면 모든 key-value
쌍을 지울 수 있다.
a = [1,2,3,4]
print(a.clear()) # None
get(key)
라는 메서드는 key
에 해당하는 value
를 준다. 이는 일반적으로 key
로 접근했을 때와 다를 바 없다. 차이는 해당하는 key
가 없을 때이다. get(key)
는 key가 없어도 에러를 반환하지 않고 None
을 반환해서 더 안전하다.
a = {'name': 'pey', 'phone': '0123451'}
print(a.get('name'), a['name']) # pey pey
print(a.get('some')) # None
print(a['some']) # KeyError: 'some'
또한, get(key)
는 두 번째 인자로, 만약 해당하는 key
가 없으면 value
를 반환해달라고 할 수 있다.
a = {'name': 'pey', 'phone': '0123451'}
print(a.get('name'), a['name']) # pey pey
print(a.get('some', 123)) # 123
print(a['some']) # KeyError: 'some'
에러로 부터 안전한 메서드이기 때문에 장점이 많다.
in
키워드는 if문이나 평문에서 'a' in 'b' 로 'a'가 'b'에 있는 지 확인할 수 있는 키워드이다. 있다면
True, 없으면
False```이다.
a = {'name': 'pey', 'phone': '0123451'}
print( 'name' in a) # True
print( 'some' in a) # False
다음과 같이 된다. 이를 통해 해당 딕셔너리에 어떤 키값이 있는 지 없는 지 확인할 수 있는 것이다.
참고로 in
은 for문과 같은 반복문에서 사용되면 순회하는 데 사용할 수 있다. 딕셔너리의 경우 key
값을 리턴해준다.
import copy
food = {'banana': 300, 'apple' : 200, 'pineapple' : 3000}
for k in food:
print(k) # banana apple pineapple
단 위에도 말했듯이 딕셔너리는 순서를 보장하지 않아서 매번 순회마다 다르다. 상위 버전의 파이썬을 쓰면 고정된 순서로 나오는데 하위버전을 그렇지 않은 것을 확인할 수 있을 것이다. 때문에 순서를 보장하지 못한다는 것을 알 수 있다.
단일 수정은 키로 접근하여 값을 바꾸면 되고, 여러 값의 수정은 update
메서드를 사용한다. 키가 없는 값이면 추가된다.
import copy
food = {'banana': 300, 'apple' : 200, 'pineapple' : 3000}
food.update({'banana': 1200 , 'apple' : 10, 'price' : 90})
print(food) # {'banana': 1200, 'apple': 10, 'pineapple': 3000, 'price': 90}
리스트나 튜플안에 key, value
형식으로 보기 좋게되어있다면 이를 dict()
로 감싸 딕셔너리로 만들 수 있다.
foods = [['apple', 3] , ['banana', 5]]
print(dict(foods)) # {'apple': 3, 'banana': 5}
foods = [('apple', 3) , ('banana', 5)]
print(dict(foods)) # {'apple': 3, 'banana': 5}
foods = (('apple', 3) , ('banana', 5))
print(dict(foods)) # {'apple': 3, 'banana': 5}
foods = (['apple', 3] , ['banana', 5])
print(dict(foods)) # {'apple': 3, 'banana': 5}
다음과 같이 리스트와 튜플 안에 키-값 쌍이 예쁘게 있다면 dict로 변환이 가능하다.
리스트와 마찬가지로 딕셔너리도 자신을 대입하면 참조값이 넘어가기 때문에, 원본이 얼마든지 수정 가능하다. 따라서 이를 조심하도록 하자
food = {'banana': 300, 'apple' : 200}
some = food
some['banana'] = 50123
print(food) # {'banana': 50123, 'apple': 200}
some을 바꾸었는데 food가 바뀐 것을 확인할 수 있다. 이를 해결하기 위해서는 copy의 deepcopy
를 사용하면 된다. deepcopy
는 새로운 객체를 만들어 값을 똑같이 만들어줄 뿐, 참조값이 넘어가는 것은 아니기 때문이다.
import copy
food = {'banana': 300, 'apple' : 200}
some = copy.deepcopy(food)
some['banana'] = 50123
print(food) # {'banana': 300, 'apple': 200}
print(some) # {'banana': 50123, 'apple': 200}
some의 값을 바꾸어도 food에 영향이 안가는 것을 확인할 수 있다.
pprint
를 사용하면 dictionary를 쉽게 표현해준다.
from pprint import pprint as pp
a = {'name' : 'gyu', 'age': 20, 'house' :'seoul'}
print(a) # {'name': 'gyu', 'age': 20, 'house': 'seoul'}
pp(a) # {'age': 20, 'house': 'seoul', 'name': 'gyu'}