Python 딕셔너리 타입 정리
≡ 목차 (Table of Contents)
이 글은 Python의 딕셔너리 타입(Dictionary Type, 사전형)과 관련된 내용을 정리한다. 예제 코드는 3.7 버전에서만 돌려봤지만 아마도 2.x 버전에서도 별 문제 없이 실행 가능할거라 생각된다.
딕셔너리 타입
Python의 딕셔너리 타입(Dictionary Type)은 dict
라는 이름의 내장 클래스로써, 하나 이상의 키를 이용해 각 키의 값을 읽거나 쓸 수 있는 타입이며, 여러 데이터를 담을 수 있어서 일반적으로 콜렉션 타입(Collection Type)의 한 종류로 분류된다.
보통 이런 종류의 자료구조로 사전형이라 부르는 타입과 동일하거나 혹은 해시맵(Hash Map), 해시테이블(Hash Table)등의 자료구조와 유사하다.
딕셔너리 인스턴스 생성
아래 명령으로 빈 딕셔너리를 생성할 수 있다.
>>> d = {}
중괄호는 Python에서 딕셔너리 타입을 정의할 때 주로 사용되기 때문에 중괄호는 곧 딕셔너리라고 인식해도 크게 틀리진 않는다.
이제 특정 키를 이용해 값을 쓸 수 있다.
>>> d['key'] = 'value' >>> d['other'] = 123 >>> d {'key': 'value', 'other': 123}
물론 한 번에 바로 생성할 수도 있다.
>>> d = {'key': 'value', 'other': 123} >>> d {'key': 'value', 'other': 123}
아예 dict
클래스의 생성자를 활용하는 방법도 있다.
>>> d = dict(key='value', other=123) >>> d {'key': 'value', 'other': 123}
매개변수로 튜플 리스트를 사용할 수도 있다.
>>> d = dict([('key', 'value'), ('other', 123)]) >>> d {'key': 'value', 'other': 123}
이 외에도 다양한 방법이 있을 수 있다.
키 읽기, 쓰기, 수정, 삭제
키의 값을 읽을 때는 배열 원소 참조하는 것과 비슷한 문법을 사용하지만 인덱스 대신 키를 사용한다는 점이 다르다.
>>> print(d['key']) value
만약 없는 키를 읽으려고 하면 KeyError
예외가 발생한다.
>>> print(d['unknown']) Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 'unknown'
굳이 예외처리를 하고 싶지 않다면 키가 없을 때의 기본 값을 지정할 수 있는 get()
메서드를 활용해서 값을 읽는 것이 편하다.
>>> print(d.get('key')) value >>> print(d.get('unknown', 'no key')) no key >>> print(d.get('another unknown')) None
get()
메서드의 두 번째 인자가 기본값이며 이 값이 지정되지 않은 경우는 None
이 기본값이 된다.
값을 쓰는 것은 제일 처음의 읽는 방법과 비슷하다.
>>> d['a'] = 'aaa' >>> d {'key': 'value', 'other': 123, 'a': 'aaa'}
하지만 set()
메서드는 별도로 없는 것 같다.
값을 수정하는 것은 그냥 값을 쓰는 것과 동일하다.
>>> d['a'] = 'aaaaa' >>> d {'key': 'value', 'other': 123, 'a': 'aaaaa'}
키를 삭제하려면 평범하게(?) del()
을 쓸 수 있다.
>>> del(d['a']) >>> d {'key': 'value', 'other': 123}
딕셔너리끼리 합치기
일반적인 방법으로 update
메서드를 활용할 수 있다.
>>> a = {'a':1, 'aa': 2} >>> b = {'b':3, 'bb': 4} >>> a.update(b) >>> a {'a': 1, 'aa': 2, 'b': 3, 'bb': 4}
update()
메서드는 원본을 변조하는 파괴적인(destructive) 방법이라 병렬 처리 시 인스턴스의 레퍼런스가 다른 태스크에서도 공유된다면 조심해서 사용해야 할 것 같다.
이 외의 트릭으로 Python 3.5 이상에서는 아래 방법을 쓸 수 있다.
>>> a = {'a': 1, 'aa': 2} >>> b = {'b': 3, 'bb': 4} >>> {**a, **b} {'a': 1, 'aa': 2, 'b': 3, 'bb': 4}
Immutable 작업 스타일로 쓸 수가 있어서 병렬 처리 환경에서도 안심하고 쓸 수 있을 것 같다.
딕셔너리에 다른 딕셔너리를 풀어 넣기
딕셔너리를 생성할 때 다른 딕셔너리의 값들을 같이 가져가려면 **
를 활용할 수 있다.
>>> a = {'john': 100} >>> b = {'james': 50, 'kim': 99} >>> c = {'lee': 98, **a, **b} >>> c {'lee': 98, 'john': 100, 'james': 50, 'kim': 99}
이건 사실 위의 합치기 두 번째 예제랑 다를 게 없다. 하지만 목적이 좀 다르게 느껴저서 별도의 항목으로 분리했다.
순회하기(Enumeration)
보통은 아래처럼 모든 키의 리스트(혹은 리스트 제너레이터)를 돌려주는 keys()
메서드를 이용해 모든 키의 값을 읽을 수 있다.
>>> d = {'key': 'value', 'other': 123} >>> for k in d.keys(): ... print(f'{k} = {d.get(k)}') ... key = value other = 123
이 외에 값들만 순회하고자 한다면 values()
메서드를 이용할 수도 있다. 하지만 그다지 쓸 일은 잘 없을 것 같다.
참고
요즘은 왠만해선 딕셔너리나 해시테이블 등의 자료구조에서 키를 문자열 형태로 사용하는 게 일반적이지만, 꼭 문자열만 키로 쓸 수 있는 것은 아니다.
>>> a = {1: 100, 2:200} >>> a {1: 100, 2: 200} >>> a[1] 100
키를 정수로 지정하면 배열과 거의 같은 모습을 구경할 수 있기도 하다.
물론 문자열이 아무래도 활용성이 좋으니 문자열 외의 타입을 키로 사용하는 일은 흔하진 않을 것이다. 아마도…