본문으로 건너뛰기
김신건의 로그

[Python] set, frozenset

· 수정 · 📖 약 1분 · 342자/단어 #python #set #frozenset #collection #basics
python set, frozenset, 파이썬 집합, set operations

정의

set중복 없는 해시 가능 원소의 가변 컬렉션이다. dict의 키 슬롯만 가진 형태로 구현되어 평균 O(1) 멤버십·삽입·삭제를 제공한다. frozenset은 그 불변 버전으로 해시 가능하다.

생성

empty = set()              # {} 는 dict! 반드시 set()
s = {1, 2, 3}
from_list = set([1, 2, 2, 3])   # {1, 2, 3} 중복 제거
comp = {x ** 2 for x in range(5)}

fs = frozenset([1, 2, 3])

함정: {}는 빈 dict이지 빈 set이 아니다.

기본 연산

python
s = {1, 2, 3}

s.add(4)
s.add(2)              # 중복 무시
print(s)

s.remove(3)           # 없으면 KeyError
s.discard(99)         # 없어도 조용
print(s)

print(2 in s)         # 멤버십 O(1)
print(len(s))
결과
{1, 2, 3, 4}
{1, 2, 4}
True
3

집합 연산

연산기호메서드의미
합집합|.union()둘 중 하나
교집합&.intersection()둘 다
차집합-.difference()A에만
대칭차^.symmetric_difference()한쪽에만
부분집합<=.issubset()A ⊆ B
진부분집합<A ⊊ B
상위집합>=.issuperset()A ⊇ B
서로소.isdisjoint()교집합 없음
python
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}

print(a | b)
print(a & b)
print(a - b)
print(a ^ b)
print({1, 2}.issubset(a))
print(a.isdisjoint({99, 100}))
결과
{1, 2, 3, 4, 5, 6}
{3, 4}
{1, 2}
{1, 2, 5, 6}
True
True

제자리 갱신

a = {1, 2, 3}
a |= {3, 4}        # 합집합 in-place: {1, 2, 3, 4}
a &= {2, 3, 4}     # 교집합 in-place: {2, 3, 4}
a -= {2}           # 차집합 in-place: {3, 4}
a ^= {3, 99}       # 대칭차 in-place: {4, 99}

# 메서드 버전
a.update({5, 6})         # |=
a.intersection_update()
a.difference_update()
a.symmetric_difference_update()

메서드와 메서드 인자 차이

연산자(|, &)는 양쪽 모두 set 타입이어야 한다. 메서드는 어떤 iterable이든 받는다.

s = {1, 2, 3}

s | [4, 5]             # TypeError
s.union([4, 5])        # OK: {1, 2, 3, 4, 5}
s.intersection_update("abc1")  # 문자열도 iter 가능

frozenset: 해시 가능 set

frozenset은 변경 불가라서 dict 키 / 다른 set의 원소로 쓸 수 있다.

python
# 그래프 무방향 엣지 표현
edges = {
  frozenset({"A", "B"}),
  frozenset({"B", "C"}),
  frozenset({"A", "B"}),    # 중복
}
print(len(edges))             # 2

# dict 키로
permissions = {
  frozenset({"read"}): "viewer",
  frozenset({"read", "write"}): "editor",
}
print(permissions[frozenset({"read", "write"})])
결과
2
editor

흔한 활용 패턴

중복 제거 (순서 무관)

unique = list(set([1, 2, 2, 3, 1]))    # [1, 2, 3] (순서 보장 X)

# 순서 보장 필요 시 → dict.fromkeys
unique = list(dict.fromkeys([1, 2, 2, 3, 1]))  # [1, 2, 3]

빠른 멤버십 검사

banned = set(load_blacklist())     # list 대신 set
for user in users:
    if user.id in banned:           # O(1)
        ...

두 컬렉션 비교

old = {"a", "b", "c"}
new = {"b", "c", "d"}

added = new - old        # {"d"}
removed = old - new      # {"a"}
unchanged = old & new    # {"b", "c"}

set vs dict vs list

상황선택
멤버십 검사 O(1)set
키-값 매핑dict
순서 보장, 중복 허용list
해시 가능한 불변 모음frozenset
순서 + 중복 제거dict.fromkeys()

함정 정리

  • {}는 dict, 빈 set은 set()
  • set은 순서 없음(3.7+ dict와 달리 보장 안 함)
  • 원소는 해시 가능해야 함 (list, dict 불가)
  • set 자체는 hashable 아님 (frozenset만)

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기