상세 컨텐츠

본문 제목

dict와 hash, defaultdict 와 frozendict

개발/python-심화(Advanced)

by Matthew0633 2022. 4. 26. 23:30

본문

python에서 key-value 구조를 가진 대표적인 자료구조가 dict 이다. sequencial 한 자료구조와 구분되어 필수적으로 사용되는데 이에 대해 깊이 살펴봤을 때 장단점을 더 잘 이해하고, 또 이를 극복한 파생된 dict 들을 공부할 수 있었다. 이러한 내용들을 정리해보고자 한다.

 

dict 의 기본 구조이기도 한 hash 구조에 대해 먼저 개념을 정리해보자

해시테이블 (hashtable)

  • hash: key-value 구조, 파이썬 엔진 자체가 강력한 hash 로 이루어진다 (Dict 자료구조가 hash구조를 활용하는 구조)
  • 장점: key 연산으로 특정 데이터에 직접 접근 가능하다. key 값을 해시함수를 활용하여 해시주소를 얻고, 이로써 value를 참조하는 형식인데 이는 적은 리소스로 많은 데이터를 효율적으로 관리한다는 면에서 장점이 있다.
  • 단점: Key 중복을 허용하지 않는다

hash 주소 존재여부 : mutable한 구조는 값이 수정될 수 있으므로, hash주소를 가지지 않는다

# Hash 값 확인
t1 = (10, 20, (30, 40, 50)) 
t2 = (10, 20, [30, 40, 50])

print( hash(t1))  # 465510690262297113
# print(hash(t2)) # 에러발생

 

setdefault 와 defaultdict

기본 dict 활용보다 속도가 빨라 대용량 데이터 처리에 많이 활용된다.

아래는 문장 내에서 word의 빈도를 계산할 때 Dict를 활용하는 간단한 코드이다.

word_counts = {}
# No use setdefault
for word in sentence:
    word_counts.setdefault(word , 0)
    word_counts[word] += 1

그런데, 매번 word가 key로서 존재하지 않을 때, default값인 0을 set해야하기 때문에 코드가 깔끔하지 않아보이는 면이 있다.

따라서 defaultdict 활용하면, 더 간결한 코드가 가능하다

from collections import defaultdict

word_counts = defaultdict(int) # 0으로 초기화 됨

# No use setdefault
for word in sentence:
    word_counts[word] += 1

 

frozen dict

dict를 immuatble 하게 사용하고자 할 수도 있을 것이다. 이 때는 MappingProxyType 에서 기존 Dict를 인자로 받아준다면 frozen dict로 사용할 수 있다.

from types import MappingProxyType

d = {'key1': 'value1'}

# Read Only
d_frozen = MappingProxyType(d)

print(d is d_frozen, d == d_frozen) # False True

d_frozen['key1'] = 'value2' # 에러 발생 (수정불가)

 

Dict 사용 시 주의 사항

Dict를 생성할 때 Comprehension도 많이 사용하지만, 중복 key가 존재할 경우는 특히나 Comprehension 사용하는 것을 지양해야한다. 왜냐하면 중복된 key의 value가 최근 value로 덮어쓰기 되어 이전 value가 담기지 않기 때문이다

source = (('k1', 'val1'),
            ('k1', 'val2'),
            ('k2', 'val3'),
            ('k2', 'val4'),
            ('k2', 'val5'))

new_dict3 = {k : v for k , v in source} # {'k1': 'val2', 'k2': 'val5'}

관련글 더보기

댓글 영역