• Home
  • About
    • Yerim Oh photo

      Yerim Oh

      Happy and worthwhile day by day :)

    • Learn More
    • Email
    • LinkedIn
    • Instagram
    • Github
    • Youtube
  • Posts
    • All Posts
    • All Tags
  • Projects

[08] Concept(파이썬 딕셔너리 기본부터 심화, try 예외처리)

06 Mar 2020

Reading time ~4 minutes

Table of Contents
  • 목차
  • 딕셔너리
    • 입력순서유지
      • collections
    • 딕셔너리의 활용 방법
      • 딕셔너리 선언
      • 딕셔너리 값 조회, 예외처리
  • 예외처리
    • 키&값 동시조회
  • 딕셔너리 키 삭제
    • 딕셔너리 모듈
      • defaultdict 객체
      • Counter 객체
        • most_common()
    • OrderedDict 객체
  • 타입 선언
    • 기존의 이름으로 타입선언
    • 기호로 선언

목차

  • 딕셔너리
    • 입력순서유지
      • collections
    • 딕셔너리의 활용 방법
      • 딕셔너리 선언
      • 딕셔너리 값 조회, 예외처리
  • 예외처리
    • 키&값 동시조회
  • 딕셔너리 키 삭제
    • 딕셔너리 모듈
      • defaultdict 객체
      • Counter 객체
        • most_common()
    • OrderedDict 객체
  • 타입 선언
    • 기존의 이름으로 타입선언
    • 기호로 선언

딕셔너리

키/값 구조로 이뤄진 딕셔너리.
파이썬 3.7+에서는 입력 순서가 유지됨
내부적으로는 해시 테이블 Hash Table 로 구현.(11장)
각 언어별 해시 테이블 구현 image

인덱스를 숫자로만 지정할 수 있는 리스트와 달리 딕셔너리는 문자를 포함해 다양한 타입을 키로 사용 가능

해시 테이블은 다양한 타입을 키로 지원,

  • 입력과 조회 모두 O(1)에 가능.
  • 물론 해시 테이블은 최악의 경우 O(n)이 될 수 있으나 대부분의 경우 훨씬 더 빨리 실행
  • 분할 상환 분석 Amortized Analysis 에 따른 시간 복잡도는 O(1).
  • 해시 테이블의 주요 연산과 시간 복잡도
연산 시간 복잡도 설명
len(a) O(1) 요소의 개수를 리턴
a[key] O(1) 키를 조회하여 값을 리턴
a[key] = value O(1) 키/값을 삽입
key in a O(1) 딕셔너리에 키가 존재하는지 확인

이처럼 딕셔너리는 대부분의 연산이 O(1)에 처리 가능한 매우 우수한 자료형임.

입력순서유지

원래 파이썬에서 딕셔너리는 입력 순서가 유지되지 않았음

  • 마찬 가지로 대부분의 언어에서 해시 테이블을 이용한 자료형은 입력 순서가 유지되지 않음.
  • 파이썬도 3.6 이하에서는 입력 순서가 유지되지 않아 collections.OrderedDict() 라는 별도 자료형을 제공했음.
  • 그러나 파이썬 3.7부터는 내부적으로 인덱스를 이용해 입력 순서를 유지하도록 개선됨.
  • 다만, 여전히 3.6 이하 버전을 사용하는 곳이 많아 인터프리터의 버전을 정확히 확인할 수 없는 상황에 서는 입력 순서가 유지되지 않을 수 있음 -> 딕셔너리의 입력 순서가 유지될 것이라고 가정하고 진행하는 것은 매우 위험하며 권장하지 않음.

  • 파이썬 3.7+: 딕셔너리 입력 순서 유지
  • 파이썬 3.6+: 딕셔너리 메모리 사용량 20% 감소

collections

파이썬 3.6 이하에서 collections.OrderedDict(): 항상 입력 순서가 유지 collections.defaultdict(): 조회 시 항상 디폴트 값을 생성해 키 오류를 방지 collections.Counter() : 요소의 값을 키로 하고 개수를 값 형태로 만들어 카운팅

딕셔너리의 활용 방법

딕셔너리 선언

>>> a = dict()

중괄호를 써서 좀 더 간단하게 선언할 수 있다.

>>> a = {}

다음과 같이 key1 , key2 는 초기값으로 지정해 선언하거나 key3 처럼 나중에 별도로 선언 하여 value3 라는 값을 할당 가능.

>>> a = {'key1':'value1', 'key2':'value2'} 

>>> a
{'key1': 'value1', 'key2': 'value2'}

>>> a['key3'] = 'value3'
>>> a
{'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}

딕셔너리 값 조회, 예외처리

키를 지정하면 가능
존재하지 않는 키를 조회할 경우에는 에러가 발생

  • try 구문으로 예외 처리
>>> a['key1']
'value1'

>>> a['key4']

Traceback (most recent call last):
File "<stdin>", line 1, in <module> KeyError: 'key4'

예외처리

try:
  print(a['key4']) 

except KeyError:
  print('존재하지 않는 키')

[PROBLEM]
KeyError 는 다음과 같이 키를 삭제할 때도 발생한다.

>>> del a['key4']

Traceback (most recent call last):
File "<stdin>", line 1, in <module> KeyError: 'key4'

[SOLVE]
try 구문으로 예외 처리
or
다음과 같이 미리 확인

>>> 'key4' in a
False

>>> if 'key4' in a:
... print('존재하는 키')
... else:
... print('존재하지 않는 키')
...
존재하지 않는 키

키&값 동시조회

키/값은 for 반복문으로 조회 가능
딕셔너리의 items() 메소드를 사용하면 키와 값을 각각 꺼내올 수 있음.

>>> for k,v in a.items():
... 	print(k,v) 
...
key1 value1
key2 value2
key3 value3

----

딕셔너리 키 삭제

**del**로 삭제

>>> del a['key1'] 
>>> a
{'key2': 'value2', 'key3': 'value3'}

딕셔너리 모듈

defaultdict 객체

존재하지 않는 키를 조회할 경우, 에러 메시지를 출력하는 대신 디폴트 값을 기준으로 해당 키에 대한 딕셔너리 아이템을 생성.
실제로는 collections.defaultdict 클래스를 갖음

없는 것 에러발생시키지 않고 디폴트값으로 만들어서 출력

>>> a = collections.defaultdict(int) 
>>> a['A'] = 5
>>> a['B'] = 4
>>> a
defaultdict(<class 'int'>, {'A': 5, 'B': 4})

>>> a['C'] += 1
>>> a
defaultdict(<class 'int'>, {'A': 5, 'B': 4, 'C': 1})

이제 C 는 존재하지 않는 키임.

원래의 딕셔너리라면 앞서 ‘딕셔너리의 활용 방법’ 절에서 살펴본 것처럼 KeyError 가 발생하겠지만,

defaultdict 객체는 에러 없이 바로 +1 연산이 가능하고 이 경우 디폴트인 0을 기준으로 자동으로 생성한 후 여기에 1을 더해 최종적으로 1이 만들어짐.

여기서도 결과를 보면 {‘A’: 5, ‘B’: 4, ‘C’: 1} , 이렇게 3개의 아이템이 존재하는 것을 확인 가능

Counter 객체

아이템에 대한 개수를 계산해 딕셔너리로 리턴

  • 키에는 아이템의 값이,
  • 값에는 해당 아이템의 개수가 들어간 딕셔너리를 생성.
    실제로는 다음과 같이 딕셔너리를 한 번 더 래핑 Wrapping 한collections.Counter 클래스를 갖음

[사용법]

>>> a = [1, 2, 3, 4, 5, 5, 5, 6, 6] 
>>> b = collections.Counter(a) 
>>> b
Counter({5: 3, 6: 2, 1: 1, 2: 1, 3: 1, 4: 1})


# 딕셔너리를 한 번 더 래핑 Wrapping 한collections.Counter 클래스
>>> type(b)
<class 'collections.Counter'>

most_common()

Counter 객체에서 가장 빈도 수가 높은 요소 추출 딕셔너리 이름.most_common(추출 개수)

>>> b.most_common(2)
[(5, 3), (6, 2)]

OrderedDict 객체

대부분의 언어에서 해시 테이블을 이용한 자료형은 입력 순서가 유지되지 않음

  • 파이썬 3.6 이하
    입력 순서가 유지되는 OrderedDict 라는 별도의 객체를 제공.
  • 입력값을 부여할 경우 OrderedDict 는 입력 그대로 순서가 유지됨.
  • OrderedDict은 순서와 관련된 몇 가지 추가 메소드를 제공한다는 점 이외에는 사실상 하위 호환성을 위해서만 남겨짐
    그러나 코딩 테스트 시 하위 버전의 파이썬 인터프리터를 사용하는 경우가 있고, 원래 해시 테이블은 입력 순서에 관여하지 않는 자료형인 만큼, 무턱대고 딕셔너리로 입력 순서를 기대하는 것은 매우 위험하며 권장하지도 않는 방법이다.
    이제는 대부분의 코딩 테스트 사이트가 3.7 이상을 사용하므로 이런 경우는 드물겠지만, 여전히 딕셔너리에서 입력 순서를 기대하는 것에는 유의 필요.
>>> collections.OrderedDict({'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2})
OrderedDict([('banana', 3), ('apple', 4), ('pear', 1), ('orange', 2)])

타입 선언

기호를 사용하여 간편하게 타입 선언

기존의 이름으로 타입선언

>>> a = list() 
>>> type(a)
<class 'list'>

기호로 선언

>>> type([])
<class 'list'>
>>> type(())
<class 'tuple'>
>>> type({})
<class 'dict'>
>>> type({1})
<class 'set'>
  • 딕셔너리와 집합
    같은 중괄호 {}를 사용하지만 키의 존재 유무로 서로 다른 자료형으로 선언


Coding test Share Tweet +1