EXCELSIOR

collections 모듈 - defaultdict 본문

Python/자료구조

collections 모듈 - defaultdict

Excelsior-JH 2017. 8. 18. 23:38

collections.defaultdict

1. defaultdict란

collections.defaultdict는 딕셔너리(dictionary)와 거의 비슷하지만 key값이 없을 경우 미리 지정해 놓은 초기(default)값을 반환하는 dictionary이다. defaultdict과 관련하여 자세한 내용은 docs.python.org에서 확인할 수 있다.

예제의 소스코드를 통해 dict(기본 딕셔너리)와 defaultdict를 비교해보면, 예제(1-1)에서 기본 딕셔너리는 해당 키가 없는 값을 출력할 경우 KeyError Exception 에러가 나타난다. 반면에 예제(1-2)에서 defaultdictdefault_factory()라는 함수로 초기값(default)를 null로 지정해줬기 때문에 해당 키가 없는 값을 출력할 경우 초기값인 null 이 출력된다.

# (1) - dict vs defaultdict
# 1-1.
import collections
ex1 = {'a':1, 'b':2}
print(ex1)
print(ex1['c'])
'''
{'b': 2, 'a': 1}
----> 4 print(ex1['c'])
5
6 # defaultdict
KeyError: 'c'
'''
# 1-2. collections.defaultdict
# defaultdict
def default_factory():
return 'null'
ex2 = collections.defaultdict(default_factory, a=1, b=2)
print(ex2)
print(ex2['c'])
'''
defaultdict(<function default_factory at 0x10ab50bf8>, {'b': 2, 'a': 1})
null
'''

2. defaultdict의 인자(factor)

collections.defaultdict(default_factory, key=value,...)default_factorykey1=value1,key2=value2,...,keyn=valuen 를 인자(factor)로 받는데, default_factorydefaultdict의 초기값을 지정하는 인자이다. 예제(2-1)에서 default_factory 인자를 넣어주지않으면 기본 딕셔너리와 마찬가지로 KeyError Exception 에러가 난다.

# (2-1) - default_factory
import collections
ex2 = collections.defaultdict(a=1, b=2)
print(ex2)
print(ex2['c'])
'''
defaultdict(None, {'b': 2, 'a': 1})
----> 6 print(ex2['c'])
KeyError: 'c'
'''
# (2-1) - default_factory
import collections
def default_factory():
return 'null'
ex2 = collections.defaultdict(default_factory, a=1, b=2)
print(ex2)
print(ex2['c'])
'''
defaultdict(<function default_factory at 0x10ab50c80>, {'b': 2, 'a': 1})
null
'''

default_factory인자는 메소드 형태의 값을 인자로 받는데, list(), int(), set()...나 사용자가 직접 메소드를 생성할 수 있다. 예제(3)은 default_factorylist(), int(), set()로 지정했을 때의 초기값을 출력하는 예제이다.

# (3) - default_factory
import collections
# 3-1. list
ex_list = collections.defaultdict(list, a=[1,2], b=[3,4])
print(ex_list)
print(ex_list['c'])
'''
defaultdict(<class 'list'>, {'b': [3, 4], 'a': [1, 2]})
[]
'''
# 3-2. set
ex_set = collections.defaultdict(set, a={1,2}, b={3,4})
print(ex_set)
print(ex_set['c'])
'''
defaultdict(<class 'set'>, {'b': {3, 4}, 'a': {1, 2}})
set()
'''
# 3-3. int
ex_int = collections.defaultdict(int, a=1, b=2)
print(ex_int)
print(ex_int['c'])
'''
defaultdict(<class 'int'>, {'b': 2, 'a': 1})
0
'''

3. dict.setdefault vs defaultdict

기본 딕셔너리(dict)에서도 defaultdict의 default_factory와 같은 기능을 하는 메소드인 setdefault를 통해 초기값을 지정할 수 있도록 제공한다. 하지만, docs.python.org에서도 확인할 수 있듯이 defaultdictdefault_factory가 더 간단하고, 더 빠르다. 예제(4)는 dict.setfault()defaultdictdefault_factory를 이용하여 리스트(s)의 원소 개수를 구하는 코드이다. 물론 이방법은 앞의 collections.Counter()를 사용하면 한줄로 구현이 가능하다.

# (4) - (s)
import collections
# 4-1. (dict)
s = ['a', 'b', 'c', 'b', 'a', 'b', 'c']
d = {}
for k in s:
d.setdefault(k, 0) # (d)
d[k] += 1
print(list(d.items()))
'''
[('b', 3), ('a', 2), ('c', 2)]
'''
# 4-2. defaultdict
dd = collections.defaultdict(int)
for k in s:
dd[k] += 1
print(list(dd.items()))
'''
[('b', 3), ('a', 2), ('c', 2)]
'''
# 4-3. - collections.Counter()
c = collections.Counter(s)
print(list(c.items()))
'''
[('b', 3), ('a', 2), ('c', 2)]
'''


'Python > 자료구조' 카테고리의 다른 글

내장함수 zip() 과 itertools.zip_longest() 함수  (0) 2017.09.21
collections 모듈 - OrderedDict  (0) 2017.09.07
collections 모듈 - namedtuple  (5) 2017.08.22
collections 모듈 - deque  (3) 2017.08.20
collections 모듈 - Counter  (7) 2017.08.17
Comments