상위 목록: 하위 목록: 작성 날짜: 읽는 데 13 분 소요

집합(Set)

Python에서는 중괄호({})를 이용하여 집합을 생성할 수 있습니다.

집합은 연산에 사용되며 중복이 불가능하며, 순서는 무관합니다.

데이터를 집합으로 변경시킨 뒤, 집합 연산으로 간단하게 데이터를 정제할 수 있습니다.


집합은 수학의 집합을 그대로 옮겨 온 자료형입니다. “이 값이 들어 있는가?”와 “두 묶음에 공통으로 들어 있는 것은 무엇인가?”처럼 포함 여부와 묶음 사이의 관계를 다룰 때 사용합니다. 예를 들어 중복된 방문자 목록에서 고유 방문자만 추리거나, 두 반 학생 명단에서 겹치는 학생을 찾는 작업을 한 줄로 처리할 수 있습니다.

제 8강에서 사용한 네 가지 기준으로 집합을 정리하면 다음과 같습니다.

  • 변경 가능(Mutable) : 원소를 추가·삭제할 수 있습니다. (변경할 수 없는 frozenset도 있습니다.)
  • 순서 없음 : 원소에 위치 번호가 없으며, 출력 순서도 넣은 순서와 관계없습니다.
  • 중복 불가 : 같은 값은 한 번만 저장됩니다.
  • 해시 기반 : 원소의 해시값으로 저장 위치를 정합니다.


집합은 제 12강의 사전에서 value 없이 key만 남긴 것과 같은 구조입니다. 원소를 넣을 때 hash(원소)로 저장할 칸을 계산하고, 그 칸에 이미 같은 값이 있으면 다시 넣지 않습니다. 이 방식 때문에 다음 세 가지 성질이 함께 생깁니다.

  1. 중복이 자동으로 제거됩니다. 같은 값은 같은 칸으로 가므로 두 번 저장되지 않습니다.
  2. in 검사가 빠릅니다. 목록은 처음부터 하나씩 비교하지만, 집합은 해시값으로 칸을 계산해 바로 확인하므로 원소가 많아도 평균적으로 거의 일정한 시간에 끝납니다.
  3. 원소는 해시 가능해야 하고, 순서가 없습니다. 저장 위치가 넣은 순서가 아니라 해시값으로 정해지기 때문입니다.

이번 강좌에서는 집합의 생성, 추가, 삭제, 변환, 포함 검사, 합집합·교집합·차집합·대칭 차집합, 포함 관계, frozenset을 다루고, 마지막에 목록·튜플·사전·집합을 한 표로 비교합니다.



생성

집합은 원소를 쉼표(,)로 구분하여 중괄호({})로 감싸서 만듭니다. 사전과 같은 중괄호를 사용하지만, key: value처럼 콜론이 없으면 집합이 됩니다.

a = {1, 2, 3}
b = {1, 3, 5, 7, 9}

print(a)
print(b)
결과
{1, 2, 3}
{1, 3, 5, 7, 9}

중괄호({})를 사용하여 집합을 생성할 수 있습니다.

예제에서는 작은 정수가 넣은 순서대로 출력되었지만, 이것은 작은 정수의 해시값이 정수 자신과 같아 우연히 크기 순서로 놓인 것일 뿐 순서가 보장되는 것은 아닙니다. 아래 차집합 절에서 순서가 바뀌어 출력되는 예를 볼 수 있습니다.


a = {}
b = set()

print(type(a))
print(type(b))
결과
<class ‘dict’>
<class ‘set’>

빈 중괄호 {}는 빈 사전(Dictionary)을 의미합니다. 빈 집합을 만들려면 반드시 set()을 사용합니다.

사전이 집합보다 먼저 Python에 들어왔기 때문에 {}는 빈 사전으로 정해져 있습니다. 빈 집합은 출력할 때도 {}가 아니라 set()으로 표시됩니다.

  • Tip : 집합은 순서가 없으므로 index로 접근할 수 없으며, 출력되는 원소의 순서도 보장되지 않습니다. 특히 문자열을 담은 집합은 실행할 때마다 출력 순서가 달라질 수 있습니다.

  • Tip : 집합의 원소는 숫자, 문자열, 튜플처럼 변경할 수 없는 값이어야 합니다. 목록은 집합의 원소가 될 수 없습니다.


a = {1, 2, 2, 3, 3, 3}
b = {1, True, 1.0}

print(a, len(a))
print(b)
print({(1, 2), 3})

try:
    {[1, 2], 3}
except TypeError as e:
    print(e)
결과
{1, 2, 3} 3
{1}
{3, (1, 2)}
cannot use ‘list’ as a set element (unhashable type: ‘list’)

{1, 2, 2, 3, 3, 3}처럼 같은 값을 여러 번 써도 한 번씩만 저장되어 길이는 3입니다.

1, True, 1.0은 ==로 비교하면 같고 해시값도 같으므로 같은 원소로 취급되어, 처음 넣은 1 하나만 남습니다.

튜플 (1, 2)는 해시 가능하므로 원소가 될 수 있지만, 목록 [1, 2]는 해시 불가능하므로 TypeError가 발생합니다. Python 3.14에서는 메시지가 cannot use 'list' as a set element (unhashable type: 'list')처럼 원인을 구체적으로 알려 줍니다.


a = {1, 2}

try:
    a[0]
except TypeError as e:
    print(e)
결과
‘set’ object is not subscriptable

집합에는 위치 번호가 없으므로 집합[0]처럼 대괄호로 원소를 꺼낼 수 없습니다. 오류 메시지 not subscriptable은 “대괄호로 원소에 접근할 수 없다”는 뜻입니다. 집합의 원소는 반복문으로 하나씩 꺼내거나 in으로 존재 여부를 확인하는 방식으로 사용합니다.



추가

집합은 변경 가능한 자료형이므로 원소를 추가할 수 있습니다. 순서가 없기 때문에 목록의 append(), insert()처럼 위치를 정하는 메서드는 없으며, 원소 하나를 넣는 add()와 여러 개를 넣는 update()를 사용합니다.

a = {1, 2, 3}
b = {1, 3, 5, 7, 9}

a.add(4)
b.add(11)

print(a)
print(b)
결과
{1, 2, 3, 4}
{1, 3, 5, 7, 9, 11}

집합.add(x)를 이용하여 집합에 x값을 가지는 원소를 추가할 수 있습니다.

add()는 원본 집합을 직접 변경하며, x의 해시값으로 저장할 칸을 계산하여 넣으므로 집합의 크기와 상관없이 빠르게 동작합니다.


a = {1, 2, 3}

print(a.add(3))
print(a)

a.update([4, 5], (6,))
print(a)
결과
None
{1, 2, 3}
{1, 2, 3, 4, 5, 6}

add()도 원본을 바꾸는 메서드이므로 None을 반환합니다. 이미 있는 값 3을 추가하면 오류 없이 아무 일도 일어나지 않습니다. 그래서 “없으면 넣는다”를 확인 없이 add() 한 번으로 처리할 수 있습니다.

집합.update(x, ...)는 x의 원소들을 하나씩 꺼내 모두 추가합니다. 목록과 튜플처럼 원소를 꺼낼 수 있는 객체를 여러 개 한꺼번에 전달할 수 있으며, 반환값은 None입니다.


a = {"x"}
b = {"x"}

a.add("ab")
b.update("ab")

print(len(a), len(b))
print(sorted(a), sorted(b))
결과
2 3
[‘ab’, ‘x’] [‘a’, ‘b’, ‘x’]

문자열을 넣을 때는 add()와 update()의 차이에 주의합니다. add("ab")는 문자열 "ab"를 원소 하나로 추가하지만, update("ab")는 문자열에서 문자를 하나씩 꺼내 'a', 'b' 두 원소를 추가합니다.

9강의 append()와 extend()의 관계와 같습니다. 문자열 집합은 실행할 때마다 출력 순서가 달라질 수 있으므로, 예제에서는 sorted()로 정렬하여 출력했습니다.



삭제

원소를 지우는 메서드는 remove(), discard(), pop(), clear() 네 가지입니다. 집합에는 위치 번호가 없으므로 모두 값을 기준으로 지우거나, 임의의 원소를 꺼냅니다.

a = {1, 2, 3}
b = {1, 3, 5, 7, 9}

a.discard(3)
b.discard(7)

print(a)
print(b)
결과
{1, 2}
{1, 3, 5, 9}

집합.discard(x)를 이용하여 집합에서 x값을 가지는 원소를 삭제할 수 있습니다.

집합은 같은 값이 하나뿐이므로, 목록의 remove()처럼 “첫 번째 원소만” 지운다는 구분이 필요 없습니다. 해시값으로 위치를 바로 찾으므로 삭제도 빠릅니다.


a = {1, 2, 3}

a.discard(10)

try:
    a.remove(10)
except KeyError as e:
    print("KeyError :", e)

print(a)
결과
KeyError : 10
{1, 2, 3}

집합.remove(x)도 원소를 삭제하지만, x가 집합에 없으면 KeyError가 발생합니다.

반면 집합.discard(x)는 x가 없어도 오류 없이 넘어갑니다.

목록의 remove()는 ValueError를 발생시키지만, 집합은 사전처럼 해시 기반이므로 KeyError를 발생시킨다는 점도 다릅니다.

  • Tip : 반드시 있어야 하는 원소를 지울 때는 remove()를 사용하여 실수를 오류로 확인하고, 있으면 지우고 없으면 넘어가도 될 때는 discard()를 사용합니다.


a = {1, 2, 3}

x = a.pop()
print(x, a)

a.clear()
print(a)

try:
    a.pop()
except KeyError as e:
    print(e)
결과
1 {2, 3}
set()
‘pop from an empty set’

집합.pop()은 임의의 원소 하나를 꺼내 반환하고 집합에서 삭제합니다. 예제에서는 1이 나왔지만, 집합에는 순서가 없으므로 어떤 원소가 나올지 정해져 있지 않다고 생각해야 합니다. 마지막에 넣은 원소가 나오는 것도 아닙니다.

집합.clear()는 모든 원소를 삭제하며, 빈 집합은 set()으로 출력됩니다. 빈 집합에서 pop()을 호출하면 KeyError가 발생합니다.



변환

다른 자료형의 데이터를 집합으로 바꾸면 중복이 한 번에 제거됩니다. 집합을 가장 많이 사용하는 경우 중 하나입니다.

L = [1, 2, 7, 2, 3]

a = set(L)

print(a)
결과
{1, 2, 3, 7}

set(x)을 이용하여 목록 x를 집합으로 변환할 수 있습니다. 목록 외에도 튜플, 문자열 등 반복 가능한 객체를 변환할 수 있습니다.

중복되는 값은 사라집니다.

set()은 목록에서 원소를 하나씩 꺼내 집합에 추가하므로, 두 번 나온 2는 한 번만 저장됩니다. 원본 목록 L은 바뀌지 않습니다.


L = [3, 1, 3, 2, 1]

print(list(set(L)))
print(sorted(set(L)))
print(list(dict.fromkeys(L)))
결과
[1, 2, 3]
[1, 2, 3]
[3, 1, 2]

중복을 제거한 뒤 다시 목록이 필요하면 list(set(목록))을 사용합니다. 단, 집합을 거치면서 원래 순서가 사라집니다. 결과가 [1, 2, 3]인 것은 정렬된 것이 아니라 작은 정수가 우연히 그 순서로 놓였기 때문이므로, 정렬된 결과가 필요하면 sorted(set(목록))처럼 명시적으로 정렬합니다.

원래 등장한 순서를 유지하면서 중복을 제거하려면 dict.fromkeys(목록)을 사용합니다. 사전의 key도 중복될 수 없고, 사전은 삽입 순서를 유지하기 때문에 [3, 1, 2]처럼 처음 나온 순서대로 남습니다.



포함 검사

집합의 가장 큰 장점은 in 연산이 빠르다는 점입니다. 금지어 목록, 이미 방문한 페이지 목록처럼 “이 값이 들어 있는가?”를 반복해서 확인하는 데이터는 목록보다 집합으로 관리하는 것이 좋습니다.

import timeit

data_list = list(range(100000))
data_set = set(data_list)

print(99999 in data_list, 99999 in data_set)

t_list = timeit.timeit(lambda: 99999 in data_list, number=100)
t_set = timeit.timeit(lambda: 99999 in data_set, number=100)

print(t_list > t_set * 100)
결과
True True
True

같은 정수 10만 개를 목록과 집합에 각각 담고, 마지막 값 99999가 들어 있는지 100번씩 확인하는 데 걸린 시간을 timeit.timeit()으로 측정했습니다.

첫 줄에서 두 검사의 결과는 똑같이 True입니다. 차이는 속도에 있습니다. 두 번째 줄의 True는 목록의 검사 시간이 집합보다 100배 이상 길었다는 뜻입니다.

목록은 99999를 찾기 위해 맨 앞의 0부터 10만 개를 차례로 비교하므로 원소 수에 비례하는 시간이 걸리지만, 집합은 hash(99999)로 칸을 계산해 바로 확인하므로 원소 수가 늘어나도 시간이 거의 늘지 않습니다.

  • Tip : 측정 시간은 컴퓨터와 실행할 때마다 달라지므로 예제에서는 시간 대신 비교 결과만 출력했습니다. 직접 print(t_list, t_set)로 시간을 출력해 보면 차이를 확인할 수 있습니다.


banned = {"spam", "ad"}
words = ["hello", "spam", "world", "ad"]

print([w for w in words if w not in banned])
결과
[‘hello’, ‘world’]

금지어를 집합 banned에 담아 두고, 단어 목록에서 금지어가 아닌 것만 남기는 예제입니다. 단어마다 w not in banned 검사를 하므로, 금지어가 많아질수록 집합을 사용하는 효과가 커집니다.

결과는 목록 words를 반복하여 만든 것이므로 원래 단어의 순서가 그대로 유지됩니다.



합집합

여기서부터는 두 집합 사이의 관계를 계산하는 집합 연산입니다. 각 연산은 기호 연산자와 메서드 두 가지 방법으로 사용할 수 있으며, 결과로 새 집합을 반환하고 원본은 바꾸지 않습니다.

a = {1, 2, 3}
b = {1, 3, 5, 7, 9}

c = a | b
d = a.union(b)

print(c)
print(d)
결과
{1, 2, 3, 5, 7, 9}
{1, 2, 3, 5, 7, 9}

| 기호를 사용하거나, 집합.union(집합)을 이용하여 합집합 연산을 할 수 있습니다.

합집합은 두 집합 중 어느 한쪽에라도 있는 원소를 모두 모은 집합입니다. 양쪽에 모두 있는 1과 3은 한 번씩만 들어갑니다.


a = {1, 2, 3}

print(a | {4})

try:
    a | [4]
except TypeError as e:
    print(e)

print(a.union([4], (5,)))
결과
{1, 2, 3, 4}
unsupported operand type(s) for |: ‘set’ and ‘list’
{1, 2, 3, 4, 5}

기호 연산자와 메서드에는 차이가 있습니다. | 연산자는 양쪽이 모두 집합이어야 하며, 목록과 연산하면 TypeError가 발생합니다.

반면 union() 메서드는 목록, 튜플처럼 원소를 꺼낼 수 있는 객체라면 무엇이든 받고, a.union([4], (5,))처럼 여러 개를 한 번에 전달할 수도 있습니다. 교집합, 차집합, 대칭 차집합의 메서드도 같은 규칙을 따릅니다.

  • Tip : 두 집합끼리 연산할 때는 읽기 쉬운 기호 연산자를, 목록 등 다른 자료형과 바로 연산할 때는 메서드를 사용합니다.



교집합

교집합은 두 데이터에서 겹치는 부분만 골라낼 때 사용합니다. 두 사용자의 공통 관심사, 두 명단에 모두 있는 사람처럼 “양쪽 모두”를 조건으로 하는 데이터를 찾을 때 유용합니다.

a = {1, 2, 3}
b = {1, 3, 5, 7, 9}

c = a & b
d = a.intersection(b)

print(c)
print(d)
결과
{1, 3}
{1, 3}

& 기호를 사용하거나, 집합.intersection(집합)을 이용하여 교집합 연산을 할 수 있습니다.

교집합은 두 집합에 모두 있는 원소만 모은 집합입니다. a와 b에 공통으로 있는 1, 3이 결과가 됩니다.


students_a = ["kim", "lee", "park"]
students_b = ["lee", "choi", "park"]

both = set(students_a) & set(students_b)

print(sorted(both))
print(sorted(set(students_a) ^ set(students_b)))
결과
[‘lee’, ‘park’]
[‘choi’, ‘kim’]

두 반의 수강생 명단에서 양쪽 모두 수강하는 학생을 찾는 예제입니다. 목록을 set()으로 바꾼 뒤 &로 교집합을 구하면, 반복문으로 하나씩 비교하지 않아도 lee와 park을 얻을 수 있습니다.

두 번째 줄은 아래에서 다룰 대칭 차집합 ^으로, 한쪽 반만 수강하는 학생 choi와 kim을 구한 것입니다. 문자열 집합은 출력 순서가 실행마다 달라질 수 있으므로 sorted()로 정렬하여 출력했습니다.


a = {1, 2, 3}
b = {2, 3, 4}
c = {3, 4, 5}

print(a & b & c)
print(a.intersection(b, c))
결과
{3}
{3}

연산자는 a & b & c처럼 이어서 쓸 수 있으며, 왼쪽부터 차례대로 계산됩니다. 메서드는 a.intersection(b, c)처럼 여러 집합을 한 번에 받습니다. 세 집합에 모두 있는 원소는 3뿐입니다.



차집합

차집합은 한쪽 데이터에서 다른 쪽에 있는 원소를 빼고 남은 것을 구합니다. 전체 회원 중 아직 출석하지 않은 회원, 이전 목록에 없던 새 항목처럼 “여기에는 있고 저기에는 없는” 데이터를 찾을 때 사용합니다.

a = {1, 2, 3}
b = {1, 3, 5, 7, 9}

c = a - b
d = b - a

print(c)
print(d)
결과
{2}
{9, 5, 7}

- 기호를 사용하거나, 집합.difference(집합)을 이용하여 차집합 연산을 할 수 있습니다.

a - b와 b - a는 결과가 다르므로 순서에 주의합니다.

차집합 a - b는 a에는 있지만 b에는 없는 원소입니다. a의 1, 2, 3 중 b에 없는 것은 2뿐입니다. 반대로 b - a는 b의 원소 중 a에 없는 5, 7, 9입니다.

  • Tip : 출력 결과 {9, 5, 7}처럼 집합은 원소를 넣은 순서나 크기 순서로 출력된다는 보장이 없습니다.

CPython에서 집합은 해시값을 내부 칸 수로 나눈 나머지 위치에 원소를 저장합니다. 원소가 3개인 b - a는 칸이 8개이므로 9는 1번 칸, 5는 5번 칸, 7은 7번 칸에 놓여 {9, 5, 7} 순서로 출력됩니다. 이처럼 작은 정수라도 크기 순서와 다르게 출력될 수 있습니다.



대칭 차집합

대칭 차집합은 두 데이터를 비교하여 어느 한쪽에만 있는 차이점을 모두 찾을 때 사용합니다. 두 버전의 목록에서 추가되거나 삭제된 항목을 한 번에 확인하는 경우가 대표적입니다.

a = {1, 2, 3}
b = {1, 3, 5, 7, 9}

c = a ^ b
d = a.symmetric_difference(b)

print(c)
print(d)
결과
{2, 5, 7, 9}
{2, 5, 7, 9}

^ 기호를 사용하거나, 집합.symmetric_difference(집합)을 이용하여 대칭 차집합 연산을 할 수 있습니다.

대칭 차집합은 두 집합 중 한쪽에만 있는 원소들의 집합으로, (a | b) - (a & b)와 같습니다.

합집합 {1, 2, 3, 5, 7, 9}에서 양쪽에 모두 있는 1, 3을 빼면 {2, 5, 7, 9}가 됩니다. 차집합과 달리 a ^ b와 b ^ a의 결과는 같습니다.


a = {1, 2, 3}
b = {2, 3, 4}

a.intersection_update(b)
print(a)

a.difference_update({2})
print(a)
결과
{2, 3}
{3}

지금까지의 연산은 모두 새 집합을 반환했지만, 결과를 원본 집합에 바로 반영하는 메서드도 있습니다. 이름 끝에 _update가 붙은 메서드는 원본을 변경하고 None을 반환합니다.

a.intersection_update(b)는 a를 a & b의 결과 {2, 3}으로 바꾸고, 이어서 a.difference_update({2})는 a에서 2를 빼 {3}으로 바꿉니다.

새 집합 반환 원본 변경 (메서드) 원본 변경 (연산자)
a | b, a.union(b) a.update(b) a |= b
a & b, a.intersection(b) a.intersection_update(b) a &= b
a - b, a.difference(b) a.difference_update(b) a -= b
a ^ b, a.symmetric_difference(b) a.symmetric_difference_update(b) a ^= b



포함 관계

두 집합 중 한쪽이 다른 쪽에 통째로 들어 있는지 확인하는 연산입니다. 예를 들어 “필수 권한을 모두 가지고 있는가?”처럼 필요한 항목이 빠짐없이 들어 있는지 검사할 때 사용합니다.

a = {1, 3}
b = {1, 3, 5, 7, 9}

print(a <= b)
print(a.issubset(b))
print(b >= a)
print(b.issuperset(a))
print(a.isdisjoint({2, 4}))
결과
True
True
True
True
True

a <= b 또는 a.issubset(b)는 a가 b의 부분집합인지 확인합니다.

b >= a 또는 b.issuperset(a)는 b가 a의 상위집합인지 확인합니다.

a.isdisjoint(x)는 두 집합에 공통 원소가 하나도 없는지 확인합니다.

a의 원소 1, 3이 모두 b에 있으므로 첫 네 줄은 모두 True이고, a와 {2, 4}는 겹치는 원소가 없으므로 마지막 줄도 True입니다.

  • Tip : |=, &=, -=, ^= 연산자를 사용하면 연산 결과로 원본 집합을 직접 변경합니다.


a = {1, 3}
b = {1, 3, 5}

print(a < b, a <= a, a < a)
print({1, 2} == {2, 1})
결과
True True False
True

<는 진부분집합, 즉 부분집합이면서 두 집합이 같지는 않은지 확인합니다. 그래서 자기 자신과 비교한 a <= a는 True지만 a < a는 False입니다.

집합에서 <, >는 크기 비교가 아니라 포함 관계를 뜻한다는 점에 주의합니다. 또한 순서가 없으므로 {1, 2}와 {2, 1}은 같은 집합입니다.



frozenset

집합은 변경 가능하므로 해시값을 계산할 수 없어, 다른 집합의 원소나 사전의 key가 될 수 없습니다. 내용이 바뀌지 않는 집합이 필요할 때는 frozenset을 사용합니다. 목록에 대한 튜플처럼, 집합에 대한 변경 불가능한 버전입니다.

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

print(a)
print(a | {4})

d = {a: "고정 집합"}
print(d[frozenset({3, 2, 1})])

try:
    a.add(4)
except AttributeError as e:
    print(e)
결과
frozenset({1, 2, 3})
frozenset({1, 2, 3, 4})
고정 집합
‘frozenset’ object has no attribute ‘add’

frozenset(x)는 x의 원소로 변경할 수 없는 집합을 만듭니다.

|, & 같은 집합 연산은 새 객체를 반환하므로 그대로 사용할 수 있으며, 결과도 frozenset입니다.

frozenset은 해시 가능하므로 사전의 key가 될 수 있습니다. 순서가 없으므로 frozenset({3, 2, 1})로 찾아도 {1, 2, 3}으로 만든 key와 같은 항목을 찾습니다.

원본을 바꾸는 add(), remove(), update() 같은 메서드는 아예 없으므로 AttributeError가 발생합니다.



정리

이름 설명 반환값/특징
{a, b}, set(x) 집합 생성 중복 제거, 빈 집합은 set()
집합.add(x) 원소 하나 추가 None, 이미 있으면 변화 없음
집합.update(x, ...) 여러 원소 추가 None
집합.remove(x) 원소 삭제 None, 없으면 KeyError
집합.discard(x) 원소 삭제 None, 없어도 오류 없음
집합.pop() 임의의 원소 꺼내기 꺼낸 원소, 비었으면 KeyError
집합.clear() 전체 삭제 None
x in 집합 존재 여부 논리값, 해시로 바로 찾음
a | b, union() 합집합 새 집합
a & b, intersection() 교집합 새 집합
a - b, difference() 차집합 새 집합, 순서에 따라 결과 다름
a ^ b, symmetric_difference() 대칭 차집합 새 집합
a <= b, a < b, isdisjoint() 포함 관계 논리값
frozenset(x) 변경 불가능한 집합 해시 가능


지금까지 배운 네 가지 자료형을 비교하면 다음과 같습니다.

기준 목록(List) 튜플(Tuple) 사전(Dictionary) 집합(Set)
표기 [1, 2] (1, 2) {"a": 1} {1, 2}
빈 객체 [] () {} set()
변경 가능 불가능 가능 가능 (frozenset은 불가능)
순서 있음 있음 삽입 순서 유지 (3.7 이상) 없음
중복 허용 허용 key 불가, value 허용 불가
접근 방법 위치 번호 위치 번호 key 접근 불가 (in, 반복만)
해시 기반 아니요 아니요 예 (key) 예
x in 검사 처음부터 차례로 비교 처음부터 차례로 비교 해시로 바로 찾음 해시로 바로 찾음
자기 자신의 해시 불가능 원소가 모두 해시 가능하면 가능 불가능 불가능 (frozenset은 가능)
원소·key 조건 제한 없음 제한 없음 key는 해시 가능 해시 가능
주 용도 순서가 있는 데이터 모음 고정된 값의 묶음 이름표로 값 찾기 중복 제거, 포함 검사, 집합 연산

순서대로 모아 두고 위치로 꺼내려면 목록, 바뀌면 안 되는 묶음이나 사전의 key가 필요하면 튜플, 이름표로 값을 찾으려면 사전, 중복을 없애거나 존재 여부를 빠르게 확인하려면 집합을 선택합니다.

댓글 남기기