Python은 collections라는 표준 라이브러리를 제공하여, 리스트, 튜플, 딕셔너리 등과 같은 내장 자료형보다 더 풍부한 데이터 구조를 지원합니다. 이번 포스팅에서는 collections 패키지에서 제공하는 deque, OrderedDict, defaultdict, Counter, namedtuple, ChainMap 등의 클래스에 대해서 알아보겠습니다.
deque 클래스는 양쪽 끝에서의 append와 pop 연산이 빠른 큐(queue)를 구현할 때 사용합니다.
내부적으로 이중 연결 리스트(doubly-linked list)를 사용하여 구현되어 있습니다.
from collections import deque
q = deque([1, 2, 3])
q.append(4)
q.appendleft(0)
print(q) # deque([0, 1, 2, 3, 4])
x = q.popleft()
print(x) # 0
print(q) # deque([1, 2, 3, 4])
defaultdict는 기본 자료형의 기능을 확장한 딕셔너리(Dictionary)의 서브클래스입니다. 이 클래스는 딕셔너리와 같은 자료구조로, 키-값 쌍을 저장합니다. 그러나 딕셔너리와는 달리, 존재하지 않는 키에 대한 값이 요청되면, defaultdict는 지정된 기본값(default)을 반환합니다.
예를 들어, defaultdict를 사용하여 문자열 리스트를 저장하는 딕셔너리를 만들고, 존재하지 않는 키에 접근할 때 기본값으로 빈 리스트를 반환하도록 설정할 수 있습니다.
Copy code
from collections import defaultdict
d = defaultdict(list)
d['foo'].append('bar')
print(d['foo']) # 출력결과: ['bar']
print(d['spam']) # 출력결과: []
위의 예제에서, defaultdict는 빈 리스트를 반환하도록 설정되어 있으므로, d[‘spam’]을 요청할 때 빈 리스트가 반환됩니다.
OrderedDict 클래스는 순서가 있는 딕셔너리를 구현할 때 사용합니다.
내부적으로 해시 테이블과 연결 리스트를 사용하여 구현되어 있습니다.
from collections import OrderedDict
d = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
print(d) # OrderedDict([('a', 1), ('b', 2), ('c', 3)])
d['d'] = 4
d['a'] = 0
print(d) # OrderedDict([('a', 0), ('b', 2), ('c', 3), ('d', 4)])
Counter는 반복 가능한(iterable) 객체에서 각 요소의 개수를 세는 자료구조입니다.
이 클래스는 딕셔너리와 유사하지만, 키(key)는 요소(element)이며 값(value)은 해당 요소의 개수입니다.
예를 들어, 문자열 리스트에서 각 문자열의 개수를 셀 수 있습니다.
from collections import Counter
words = ['hello', 'world', 'hello', 'world', 'python']
c = Counter(words)
print(c) # 출력결과: Counter({'hello': 2, 'world': 2, 'python': 1})
위의 예제에서, Counter는 각 문자열의 개수를 세어 딕셔너리 형태로 반환합니다.
namedtuple은 Python의 collections 모듈에 포함된 클래스로, 튜플(tuple)의 서브클래스입니다.
이 클래스는 이름(name)으로 구성된 필드(field)를 가진 튜플을 생성하며, 각 필드에는 이름이 부여되어 있어 해당 이름을 통해 필드에 접근할 수 있습니다.
from collections import namedtuple
Person = namedtuple('Person', ['name', 'age', 'gender'])
person1 = Person(name='Alice', age=30, gender='female')
person2 = Person(name='Bob', age=25, gender='male')
print(person1) # 출력결과: Person(name='Alice', age=30, gender='female')
print(person1.name) # 출력결과: Alice
print(person2) # 출력결과: Person(name='Bob', age=25, gender='male')
print(person2.age) # 출력결과: 25
chainmap은 여러 개의 딕셔너리를 하나의 딕셔너리로 합치는 기능을 제공합니다.
이 기능은 여러 개의 딕셔너리를 차례대로 검색할 필요 없이, 하나의 딕셔너리로 모두 검색할 수 있도록 도와줍니다.
단, key가 중복일 경우, 가장 먼저 나오는 딕셔너리의 값을 사용합니다.
from collections import ChainMap
dict1 = {'a': 1, 'b': 2}
dict2 = {'b': 3, 'c': 4}
combined_dict = ChainMap(dict1, dict2)
print(combined_dict['a']) # 1
print(combined_dict['b']) # 2
print(combined_dict['c']) # 4
dict1['a'] = 5
print(combined_dict['a']) # 5