Programming Languages/Python
collections 모듈의 특수 컬렉션
newclass
2025. 3. 26. 02:14
collections 모듈의 특수 컬렉션
파이썬의 collections 모듈은 기본 자료구조를 확장한 특수 컨테이너 자료형을 제공합니다. 자주 사용되는 몇 가지를 살펴보겠습니다.
Counter: 요소 개수 세기
Counter는 해시 가능한 객체의 개수를 세는 딕셔너리 하위 클래스입니다. 요소를 키로, 개수를 값으로 저장합니다.
from collections import Counter
# 문자열의 문자 개수 세기
text = "mississippi"
char_count = Counter(text)
print(char_count) # Counter({'i': 4, 's': 4, 'p': 2, 'm': 1})
# 단어 빈도 세기
words = ["apple", "orange", "banana", "apple", "orange", "apple"]
word_count = Counter(words)
print(word_count) # Counter({'apple': 3, 'orange': 2, 'banana': 1})
# 가장 흔한 요소
print(char_count.most_common(2)) # [('i', 4), ('s', 4)]
# 산술 연산
counter1 = Counter(a=3, b=1, c=2)
counter2 = Counter(a=1, b=2, d=3)
print(counter1 + counter2) # Counter({'a': 4, 'd': 3, 'b': 3, 'c': 2})
print(counter1 - counter2) # Counter({'a': 2, 'c': 2}) (음수 결과는 제외됨)
# elements() 메서드: 요소를 개수만큼 반복
print(list(counter1.elements())) # ['a', 'a', 'a', 'b', 'c', 'c']
defaultdict: 기본값을 갖는 딕셔너리
defaultdict는 존재하지 않는 키에 접근할 때 지정한 기본값(또는 기본값 생성 함수)을 반환하는 딕셔너리입니다.
from collections import defaultdict
# int 기본값을 갖는 defaultdict (기본값: 0)
int_dict = defaultdict(int)
print(int_dict["no_key"]) # 0 (에러 없음)
int_dict["a"] += 1
int_dict["b"] += 2
print(int_dict) # defaultdict(<class 'int'>, {'no_key': 0, 'a': 1, 'b': 2})
# list 기본값을 갖는 defaultdict (기본값: [])
list_dict = defaultdict(list)
list_dict["fruits"].append("apple")
list_dict["fruits"].append("banana")
list_dict["vegetables"].append("carrot")
print(list_dict) # defaultdict(<class 'list'>, {'fruits': ['apple', 'banana'], 'vegetables': ['carrot']})
# 사용자 정의 기본값 함수
def get_default_value():
return "default value"
custom_dict = defaultdict(get_default_value)
print(custom_dict["any_key"]) # "default value"
# 그룹화 예제 (카테고리별로 항목 그룹화)
items = [
("과일", "사과"),
("채소", "당근"),
("과일", "바나나"),
("과일", "오렌지"),
("채소", "브로콜리"),
("유제품", "치즈")
]
categorized = defaultdict(list)
for category, item in items:
categorized[category].append(item)
print(dict(categorized)) # {'과일': ['사과', '바나나', '오렌지'], '채소': ['당근', '브로콜리'], '유제품': ['치즈']}
OrderedDict: 순서를 기억하는 딕셔너리
OrderedDict는 항목이 삽입된 순서를 기억하는 딕셔너리입니다. Python 3.7부터 일반 딕셔너리도 삽입 순서를 유지하지만, OrderedDict는 항목의 순서를 변경하는 등의 추가 기능을 제공합니다.
from collections import OrderedDict
# OrderedDict 생성
ordered = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
print(ordered) # OrderedDict([('a', 1), ('b', 2), ('c', 3)])
# 일반 딕셔너리와 OrderedDict 비교
d1 = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
d2 = OrderedDict([('c', 3), ('a', 1), ('b', 2)])
print(d1 == d2) # False (순서가 다름)
regular1 = {'a': 1, 'b': 2, 'c': 3}
regular2 = {'c': 3, 'a': 1, 'b': 2}
print(regular1 == regular2) # True (Python 3.7+ 에서도 순서가 다르지만, 비교 시 순서 무시)
# 순서 관련 특수 메서드
ordered.move_to_end('a') # 'a'를 맨 뒤로 이동
print(ordered) # OrderedDict([('b', 2), ('c', 3), ('a', 1)])
ordered.move_to_end('c', last=False) # 'c'를 맨 앞으로 이동
print(ordered) # OrderedDict([('c', 3), ('b', 2), ('a', 1)])
namedtuple: 이름 있는 필드를 가진 튜플
namedtuple은 필드에 이름을 붙일 수 있는 튜플의 하위 클래스를 생성합니다. 이름으로 필드에 접근할 수 있고, 클래스처럼 사용할 수 있어 가독성이 좋아집니다.
from collections import namedtuple
# Point 클래스 정의 (x, y 필드를 가진 namedtuple)
Point = namedtuple('Point', ['x', 'y'])
# 인스턴스 생성
p1 = Point(1, 2)
p2 = Point(x=3, y=4)
# 필드 접근
print(p1.x, p1.y) # 1 2
print(p2[0], p2[1]) # 3 4 (일반 튜플처럼 인덱스로도 접근 가능)
# 튜플로서의 특성 (언패킹)
x, y = p1
print(x, y) # 1 2
# 변경 시도 (오류)
try:
p1.x = 10 # AttributeError: can't set attribute
except AttributeError as e:
print(f"오류 발생: {e}")
# 메서드와 속성
print(p1._fields) # ('x', 'y') (필드 이름 튜플)
p3 = p1._replace(x=10) # 새 인스턴스 생성 (원본 변경 X)
print(p1) # Point(x=1, y=2)
print(p3) # Point(x=10, y=2)
# 사용 예시: 학생 정보
Student = namedtuple('Student', ['name', 'age', 'major', 'gpa'])
students = [
Student('김철수', 20, '컴퓨터공학', 3.5),
Student('이영희', 22, '경영학', 3.8),
Student('박민수', 21, '전자공학', 4.0)
]
for student in students:
print(f"{student.name}({student.age}세): {student.major}, 평점 {student.gpa}")