티스토리 뷰

반응형

파이썬의 사전 타입

사전은 파이썬에서 기본적으로 제공되는 유일한 맵핑 혹은 해시테이블 타입이다. 사전은 특정한 요소를 찾기 위해 키(key)를 사용한다. 보통은 문자열을 키로 사용하는데, 기본적으로 '변경 불가능'한 파이썬의 기본 타입들은 모두 키가 될 수 있다. (문자열, 정수, 실수, 튜플)

사전 만들기

사전을 생성하는 방법은 다음과 같은 것들이 있다.

  1. dict() 생성자 함수를 이용한다.
  2. 사전 리터럴을 이용한다.

사전 리터럴은 중괄호 속에 키: 값(콜론으로 구분)의 쌍을 다시 컴마로 구분하여 적는 것이다. dict() 함수를 이용한다면 (키, 값)으로 구성된 튜플의 연속열을 인자로 주면 된다.

d1 = { 'a':1, 'b':2, 'c':3, 'd':4 }
d2 = dict([('a', 1), ('b', 2), ('c', 3), ('d': 4)])

두 번째 방법은 아무래도 좀 불편한 감이 있어 보인다. 따라치는 타이핑만해도 틀릴 소지가 많지 않던가.

너무나 기본적이어서 간과하고 지나치는 점인데, 이러한 기본적인 데이터 타입에 대한 내용을 공부할 때는 인터랙티브 쉘이나 노트북에서 더미 값을 만들어서 이것 저것 시험해보는 게 중요하다. 그런데 사전이 이렇게 만들기가 어려워서야.... 그래서 기본 함수를 이용해서 쉽게 더미 사전을 만드는 테크닉을 소개하면 다음과 같다.

d3 = dict(zip('abcd', range(1, 5))

zip 함수는 두 개의 연속열을 "엮어서" 연속열들의 각 원소들의 쌍의 제너레이터를 만들어 낸다. (지퍼처럼 양쪽에서 하나씩 잡아서 물려준다는 의미로 이해하면 된다.)

사전의 주요 사용법

원소 액세스

사전은 리스트와는 달리 내부 원소들 간에 순서가 없다. 원소들은 인덱스가 아닌 '키'에 의해 액세스된다. 사전의 멋진 점은 키의 해시를 이용해서 원소를 찾기 때문에, 원소를 탐색하는 시간이 매우 짧다는 것이다. (이상적인 경우 $O_{(n)}$이 된다.

  • d[key] : key에 해당하는 값을 찾음
  • d[key] = value : 사전에 key에 해당한 키의 값을 설정함
  • key in d : 특정 키가 사전에 있는지 검사
  • key not in d : not (key in d)를 좀 더 읽기 쉽게 쓰는 문법적 장식

원소 순회하기

.keys(), .values()를 이용하면 사전의 키나 값들을 for 문을 통해서 순회할 수 있다. .items()(키, 값)쌍의 튜플을 순회할 수 있다.

원소 제거하기

한 번 추가된 원소를 같은 키에 다른 값을 대입하는 식으로 업데이트 할 수 있다. 이 값은 None으로도 업데이트될 수 있는데, 이 경우에는 (key, None) 의 값을 가지는 것이며, 해당 키, 값 쌍을 제거하는 것이 아니다. 제거를 위해서는 .del(key) 메소드를 사용할 수 있다.

기본 값 사용하기

예를 들어 어떤 사전에 특정한 키가 있으면 그 값을 이용하고, 없으면 초기 값을 만들어 준 다음에 사용해야 하는 경우가 있을 수 있다. (의외로 생각보다 자주 이런 경우를 접할 수 있다.) 흔히 특정한 글에서 단어가 나타나는 횟수를 세는 경우에 그럴 수 있을 것이다.

words = """아주 긴 문자열""".split()
wordsCounts = dict()
for word in words:
    if word in wordsCount:
        wordsCount[word] += 1
    else:
        wordsCount[word] = 1
       

만약, 사전에 특정한 키를 업데이트하려 할 때, 디폴트로 어떤 값을 쓰겠다고 정했다면, get(key, defaultValue)를 사용할 수 있다.

for word in words:
    wordsCount[word] = wordsCount.get(word, 0) + 1

.get()은 특정한 키가 없다면, 다른 값을 리턴하는 메소드지만 이것은 사전의 내용에는 영향을 끼치지 않는다. 대신 .setdefault(key, default).get()과 똑같지만, 디폴트 값을 리턴하는 시점에 (key, default) 의 쌍을 사전에 추가해준다.

사전의 쓰임새

사전은 기본적으로 '키'를 통해서 특정한 내부 원소를 액세스할 수 있고, 또 값이 될 수 있는 타입에는 제한이 없으므로 (튜플은 물론 리스트나 다른 사전이 값이 될 수 있다.) 익명의 클래스를 대신할 수 있다. 예를 들어 어떤 반의 학생의 이름과, 국어, 영어, 수학 점수를 관리하는 코드를 작성한다고 하자. 이 때 별도의 Student라는 클래스를 만들 필요 없이, 사전을 쓰면 된다. "이름", "국어", "영어", "수학"의 문자열을 속성이름 대신에 키로 쓰면 되는 것이다.

또한 어떤 키가 사전 내에 포함되어 있는지 여부를 매우 빠르게 판단할 수 있다고 했다. 따라서 어떤 함수의 계산 결과를 저장해두는 캐시로 쓸 수 있다. 다음은 피보나치 수열의 일반항을 구하는 함수를 캐시를 이용해서 속도를 높이는 예이다.

cache = {1: 0, 2: 1}

def fib(n: int) -> int:
    if n in cache:
        return cache[n]
    r = fib(n-1) + fib(n-2)
    cache[n] = r
    return r

%time fib(100)
# Wall time: 0 ns
# Out[9]: 218922995834555169026

사전은 사실 파이썬 내부에서 매우 광범위하게 쓰인다. 전역변수, 특정한 함수의 지역변수, 그리고 특정 클래스와 객체 인스턴스내의 이름공간은 파이썬 사전으로 구성된다. 내장함수인 locals()globals()는 현재 스코프에서의 이름공간에 정의된 모든 바인딩을 사전으로 리턴해준다. 그리고 클래스 객체내에서의 애트리뷰트 이름과 값도 모두 사전으로 만들어져 있다.

반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함