11. 튜플과 집합




1 튜플 활용법


  • 튜플(Tuples): 순서있는 임의의 객체 모음 (시퀀스형)
  • 튜플은 변경 불가능(Immutable)
  • 시퀀스형이 가지는 다음 연산 모두 지원
    • 인덱싱, 슬라이싱, 연결, 반복, 멤버쉽 테스트

1-1 튜플 연산

In [1]:
t1 = ()      # 비어있는 튜플
t2 = (1,2,3) # 괄호 사용

t3 = 1,2,3   # 괄호가 없어도 튜플이 됨
print(type(t1), type(t2), type(t3))


# <type 'tuple'> <type 'tuple'> <type 'tuple'>
<class 'tuple'> <class 'tuple'> <class 'tuple'>
In [2]:
r1 = (1,) # 자료가 한 개일 때는 반드시 콤마가 있어야 한다.
r2 = 1,   # 괄호는 없어도 콤마는 있어야 한다.
print(type(r1))
print(type(r2))

# <type 'tuple'>
# <type 'tuple'>
<class 'tuple'>
<class 'tuple'>
In [3]:
t = (1, 2, 3)
print(t * 2)                  # 반복
print(t + ('PyKUG', 'users'))  # 연결
print(t)
print()

print(t[0], t[1:3])            # 인덱싱, 슬라이싱
print(len(t))                  # 길이
print(1 in t)                  # 멤버십 테스트
(1, 2, 3, 1, 2, 3)
(1, 2, 3, 'PyKUG', 'users')
(1, 2, 3)

1 (2, 3)
3
True
In [4]:
t[0] = 100 # 튜플은 변경 불가능, 에러발생
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-ded308ebf8b1> in <module>()
----> 1 t[0] = 100 # 튜플은 변경 불가능, 에러발생

TypeError: 'tuple' object does not support item assignment
In [5]:
t = (12345, 54321, 'hello!') 
u = t, (1, 2, 3, 4, 5) # 튜플 내부 원소로 다른 튜플을 가질 수 있음
print(u)

t2 = [1, 2, 3] # 튜플 내부 원소로 리스트 가질 수 있음 
u2 = t2, (1, 2, 4)
print(u2)

t3 = {1:"abc", 2:"def"} # 튜플 내부 원소로 사전 가질 수 있음 
u3 = t3, (1, 2, 3)
print(u3)
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
([1, 2, 3], (1, 2, 4))
({1: 'abc', 2: 'def'}, (1, 2, 3))
In [6]:
x, y, z = 1, 2, 3 # 튜플을 이용한 복수 개의 자료 할당
print(type(x), type(y), type(z))
print(x)
print(y)
print(z)


# <type 'int'> <type 'int'> <type 'int'>
# 1
# 2
# 3
<class 'int'> <class 'int'> <class 'int'>
1
2
3
In [7]:
x = 1
y = 2
x, y = y, x # 튜플을 이용한 두 자료의 값 변경
print(x, y)
2 1

1-2 패킹과 언패킹

  • 패킹 (Packing): 하나의 튜플 안에 여러 개의 데이터를 넣는 작업
In [8]:
t = 1, 2, 'hello'
  • 언패킹 (Unpacking): 하나의 튜플에서 여러 개의 데이터를 한꺼번에 꺼내와 각각 변수에 할당하는 작업
In [9]:
x, y, z = t
  • 리스트로도 비슷한 작업이 가능하지만, 단순 패킹/언패킹 작업만을 목적으로 한다면 튜플 사용 추천
In [5]:
a = ['foo', 'bar', 4, 5]
[x, y, z, w] = a
print(x)
print(y)
print(z)
print(w)
print()

x, y, z, w = a
print(x)
print(y)
print(z)
print(w)
foo
bar
4
5

foo
bar
4
5
  • 튜플과 리스트와의 공통점

    • 원소에 임의의 객체를 저장
    • 시퀀스 자료형
      • 인덱싱, 슬라이싱, 연결, 반복, 멤버쉽 테스트 연산 지원
  • 리스트와 다른 튜플만의 특징

    • 변경 불가능 (Immutable)
    • 튜플은 count와 index 외에 다른 메소드를 가지지 않는다.
In [13]:
T = (1, 2, 2, 3, 3, 4, 4, 4, 4, 5)
print(T.count(4))
print(T.index(1))
4
0
  • list() 와 tuple() 내장 함수를 사용하여 리스트와 튜플을 상호 변환할 수 있음
In [14]:
T = (1, 2, 3, 4, 5)
L = list(T)
L[0] = 100
print(L)

T = tuple(L)
print(T)
[100, 2, 3, 4, 5]
(100, 2, 3, 4, 5)

1-3 튜플의 사용 용도

  • 튜플을 사용하는 경우 1: 함수가 하나 이상의 값을 리턴하는 경우
In [12]:
def calc(a, b):
    return a+b, a*b

x, y = calc(5, 4)
  • 튜플을 사용하는 경우 2: 문자열 포멧팅
In [13]:
print('id : %s, name : %s' % ('gslee', 'GangSeong'))
id : gslee, name : GangSeong
  • 튜플을 사용하는 경우 3: 고정된 값을 쌍으로 표현하는 경우
In [15]:
d = {'one':1, 'two':2}
print(d.items())


# [('two', 2), ('one', 1)]
dict_items([('one', 1), ('two', 2)])

2 집합 자료형


  • set 내장 함수를 사용한 집합 자료 생성
    • 변경 가능(Mutable)한 객체이다.
    • 각 원소간에 순서는 없다.
    • 각 원소는 중복될 수 없다.
    • [note] set은 컨네이너 자료형이지만 시퀀스 자료형은 아니다.

2-1 집합 자료형 생성

In [33]:
a = set([1, 2, 3])
print(type(a))
print(a)
<class 'set'>
{1, 2, 3}
In [34]:
b = set((1, 2, 3))
print(type(b))
print(b)
<class 'set'>
{1, 2, 3}
In [35]:
c = set({'a':1, 'b':2, 'c':3})
print(type(c))
print(c)
<class 'set'>
{'c', 'a', 'b'}
In [36]:
d = set({'a':1, 'b':2, 'c':3}.values())
print(type(d))
print(d)
<class 'set'>
{1, 2, 3}
  • set의 원소로는 변경 불가능(Immutable)한 것만 할당 가능하다.
In [18]:
print(set())                         # 빈 set 객체 생성
print(set([1, 2, 3, 4, 5]))         # 초기 값은 일반적으로 시퀀스 자료형인 리스트를 넣어준다.
print(set([1, 2, 3, 2, 3, 4]))      # 중복된 원소는 한 나만 저장됨
print(set('abc'))                  # 문자열은 각 문자를 집합 원소로 지닌다.  
print(set([(1, 2, 3), (4, 5, 6)]))  # 각 튜플은 원소로 가질 수 있음 
print(set([[1, 2, 3], [4, 5, 6]]))  # 변경 가능 자료인 리스트는 집합의 원소가 될 수 없다.
set()
{1, 2, 3, 4, 5}
{1, 2, 3, 4}
{'c', 'a', 'b'}
{(4, 5, 6), (1, 2, 3)}
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-18-3b8ead7ab089> in <module>()
      4 print(set('abc'))                  # 문자열은 각 문자를 집합 원소로 지닌다.
      5 print(set([(1, 2, 3), (4, 5, 6)]))  # 각 튜플은 원소로 가질 수 있음
----> 6 print(set([[1, 2, 3], [4, 5, 6]]))  # 변경 가능 자료인 리스트는 집합의 원소가 될 수 없다.

TypeError: unhashable type: 'list'
  • set의 기본 연산
set 연산 동일 연산자 내용
len(s) 원소의 개수
x in s x가 집합 s의 원소인가?
x not in s x가 집합 s의 원소가 아닌가?
In [19]:
A = set([1,2,3,4,5,6,7,8,9])

print(len(A))      # 집합의 원소의 수
print(5 in A)      # 멤버십 테스트
print(10 not in A) # 멤버십 테스트
9
True
True

2-2 집합 자료형 메소드

  • set의 주요 메소드
    • 다음 연산은 원래 집합은 변경하지 않고 새로운 집합을 반환한다.
set 연산 동일 연산자 내용
s.issubset(t) s <= t s가 t의 부분집합인가?
s.issuperset(t) s >= t s가 t의 슈퍼집합인가?
s.union(t) s | t 새로운 s와 t의 합집합
s.intersection(t) s & t 새로운 s와 t의 교집합
s.difference(t) s - t 새로운 s와 t의 차집합
s.symmetric_difference(t) s ^ t 새로운 s와 t의 배타집합
s.copy() 집합 s의 shallow 복사
In [20]:
B = set([4, 5, 6, 10, 20, 30])
C = set([10, 20, 30])

print(C.issubset(B))    # C가 B의 부분집합?
print(C <= B)
print(B.issuperset(C))  # B가 C를 포함하는 집합?
print(B >= C)
print()
True
True
True
True

In [37]:
A = set([1, 2, 3, 4, 5, 6, 7, 8, 9])
B = set([4, 5, 6, 10, 20, 30])

print(A.union(B)) # A와 B의 합집합
print(A | B)
print(A)
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30}
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30}
{1, 2, 3, 4, 5, 6, 7, 8, 9}
In [38]:
print(A.intersection(B)) # A와 B의 교집합
print(A & B)
print(A)
{4, 5, 6}
{4, 5, 6}
{1, 2, 3, 4, 5, 6, 7, 8, 9}
In [39]:
print(A.difference(B)) # A - B (차집합)
print(A - B)
print(A)
{1, 2, 3, 7, 8, 9}
{1, 2, 3, 7, 8, 9}
{1, 2, 3, 4, 5, 6, 7, 8, 9}
In [40]:
print(A.symmetric_difference(B)) # 베타집합. A와 B의 합집합에서 교집합의 원소를 제외한 집합
print(A ^ B)
print(A)
{1, 2, 3, 7, 8, 9, 10, 20, 30}
{1, 2, 3, 7, 8, 9, 10, 20, 30}
{1, 2, 3, 4, 5, 6, 7, 8, 9}
In [25]:
A = set([1,2,3,4,5,6,7,8,9])
D = A.copy()
print(D)
print()

print(A == D) #자료값 비교
print(A is D) #객체 동등성 비교
{1, 2, 3, 4, 5, 6, 7, 8, 9}

True
False
  • set은 시퀀스 자료형이 아니므로 인덱싱, 슬라이싱, 정렬 등을 지원하지 않는다.
In [26]:
A = set([1, 2, 3, 4, 5, 6, 7, 8, 9])
print(A[0])
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-26-a63b022b1bfc> in <module>()
      1 A = set([1, 2, 3, 4, 5, 6, 7, 8, 9])
----> 2 print(A[0])

TypeError: 'set' object does not support indexing
In [27]:
print(A[1:4])
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-27-6528a6e43456> in <module>()
----> 1 print(A[1:4])

TypeError: 'set' object is not subscriptable
In [28]:
print(A.sort())
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-28-741fa0d5986b> in <module>()
----> 1 print(A.sort())

AttributeError: 'set' object has no attribute 'sort'
  • 집합을 리스트나 튜플로 변경가능
    • 집합에 인덱싱, 슬라이싱, 정렬 등을 적용하기 위해서는 리스트나 튜플로 변경한다.
In [29]:
print(list(A))
print(tuple(A))
[1, 2, 3, 4, 5, 6, 7, 8, 9]
(1, 2, 3, 4, 5, 6, 7, 8, 9)
  • 하지만 집합에 for ~ in 연산은 적용 가능하다.
In [30]:
A = set([1, 2, 3, 4, 5, 6, 7, 8, 9])
for ele in A:
    print(ele,end=" ")
1 2 3 4 5 6 7 8 9 
  • set은 변경 가능(Mutable)한 자료 구조 객체
  • 다음 메소드들은 set을 변경하는 집합 자료 구조 메소드들임
set 연산 동일 연산자 내용
s.update(t) s |= t s와 t의 합집합을 s에 저장
s.intersection_update(t) s &= t s와 t의 교집합을 s에 저장
s.difference_update(t) s -= t s와 t의 차집합을 s에 저장
s.symmetric_difference_update(t) s ^= t s와 t의 배타집합을 s에 저장
s.add(x) 원소 x를 집합 s에 추가
s.remove(x) 원소 x를 집합 s에서 제거, 원소 x가 집합 s에 없으면 예외 발생
s.discard(x) 원소 x를 집합 s에서 제거
s.pop() 임의의 원소를 집합 s에서 제거, 집합 s가 공집합이면 예외 발생
s.clear() 집합 s의 모든 원소 제거
In [42]:
A = set([1, 2, 3, 4])
B = set([3,4, 5, 6])

A.update(B) # A에 B 집합의 원소를 추가 시킴
print(A)
{1, 2, 3, 4, 5, 6}
In [44]:
A.intersection_update([4,5,6,7,8]) # &=
print(A)
{4, 5, 6}
In [45]:
A.difference_update([6,7,8]) # -=
print(A)
{4, 5}
In [46]:
A.symmetric_difference_update([5,6,7]) # ^=
print(A)
{4, 6, 7}
In [47]:
A.add(8)    # 원소 추가
print(A)
{4, 6, 7, 8}
In [48]:
A.remove(8) # 원소 제거
print(A)
{4, 6, 7}
In [49]:
A.remove(10) # 없는 원소를 제거하면 KeyError 발생
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-49-cf6ee77daf41> in <module>()
----> 1 A.remove(10) # 없는 원소를 제거하면 KeyError 발생

KeyError: 10
In [50]:
A.discard(10) # remove와 같으나 예외가 발생하지 않음
A.discard(6)  # 원소 6제거
print(A)
{4, 7}
In [51]:
A.pop() # 임의의 원소 하나 꺼내기
print(A)
{7}
In [53]:
A = set([1,2,3,4])
A.clear() # 모든 원소 없애기
print(A)
set()

참고 문헌: 파이썬(열혈강의)(개정판 VER.2), 이강성, FreeLec, 2005년 8월 29일