본문 바로가기
Python

[Python] 튜플(tuple) 자료형 사용법 및 예제

by A6K 2022. 10. 31.

 파이썬의 튜플은 여러 데이터를 묶어서 같이 처리할 수 있게 해주는 자료형 중 하나다. 위키백과에서 설명하는 튜플은 "셀 수 있는 수랴의 순서 있는 열거"다. 튜플은 리스트와 거의 유사하게 사용할 수 있다. 하지만 몇 가지 차이점이 있다.

튜플은 리스트와 비교해 다음과 같은 차이점을 갖는다.

  1. 튜플을 생성하기 위해서는 대괄호'[', ']'가 아닌 소괄호 '(', ')'를 사용한다
  2. 튜플은 생성한 이후 값을 바꿀 수 없다.

리스트와 튜플은 비슷한 역할을 한다. 여러 값들을 하나의 덩어리로 가지고 다니면서 다루고, 각 엘리먼트들에는 순서가 있기 때문에 얼핏 같은 용도로 사용할 수 있다. 하지만 리스트와 튜플은 분명한 차이점이 있고, 이를 구별해서 알맞은 곳에 쓰는 것이 좋다. 리스트는 항목의 값들이 변경될 수 있는 곳에 쓰는 것이 좋고, 튜플은 리턴된 값을 바꿀 일이 전혀 없을 곳에 쓰는게 좋다.(튜플은 값을 바꾸려고 할 때 에러를 발생시키므로 값이 바뀌지 않음을 보장할 수 있다)

튜플의 생성

튜플은 소괄호를 이용해 생성할 수 있다.

empty_tuple = ()
tuple1 = ('apple',)
tuple2 = ('apple', 'banana')
tuple3 = 'apple', 'banana', 'orange'
tuple4 = ('apple', ('banana', 'orange'), 'mango')

리스트가 대괄호를 이용해 생성할 수 있었다면 튜플은 소괄호를 이용해 생성할 수 있다. 소괄호에 아무것도 넣지 않으면 빈 튜플(empty_tuple)이 만들어진다.

튜플에 포함시키고 싶은 엘리먼트들은 소괄호 안쪽에 콤마로 구분해서 넣어주면 된다. 리스트와 마찬가지로 튜플에 포함되어 있는 엘리먼트들이 반드시 같은 타입이어야 하는 것은 아니다. 문자열 여러개를 하나의 튜플에 사용(tuple2)할 수도 있고, 다른 튜플을 엘리먼트로하는 튜플(tuple4)을 만들 수도 있다.

흥미로운 점은 튜플을 생성할 때 소괄호를 쓰지 않아도 된다는 점(tuple3)이다. 그냥 콤마로 여러 값들을 나열하면 알아서 튜플로 해석된다.

엘리먼트 하나짜리 튜플(tuple1)을 만들고 싶다면 소괄호에 엘리먼트 하나를 넣고 콤마를 뒤에 붙여준다. 만약 콤마를 붙이지 않으면 튜플이 아닌 엘리먼트 자체가 사용된다.

예를 들어 다음 코드를 보면

t1 = 1
t2 = (1)
t3 = (1,)

print(type(t1))
print(type(t2))
print(type(t3))

# <class 'int'>
# <class 'int'>
# <class 'tuple'>

 소괄호를 사용해 엘리먼트 하나를 입력한 t2는 튜플 타입이 아닌 int 타입으로 다뤄지는 것을 볼 수 있다.

튜플 요소 접근

파이썬의 튜플에 담겨 있는 각 엘리먼트들은 순서가 정해져 있다. 따라서 엘리먼트에 접근할 때 몇 번째 엘리먼트에 접근할지 인덱스(index) 값을 사용한다. 리스트와 마찬가지다.

fruits = ('apple', 'banana', 'pear', 'strawberry', 'cherry')
print(fruits[0])
print(fruits[1])
print(fruits[2])
print(fruits[3])
print(fruits[4])

# apple
# banana
# pear
# strawberry
# cherry

만약 존재하지 않는 범위의 인덱스를 사용한다면, 예를 들어 5개의 엘리먼트가 있는 튜플의 엘리먼트들은 0~4번 인덱스를 사용한다. 이 때, 5번 인덱스를 이용해 접근하는 경우에는 IndexError가 발생한다.

fruits = ('apple', 'banana', 'pear', 'strawberry', 'cherry')
print(fruits[0])
print(fruits[1])
print(fruits[2])
print(fruits[3])
print(fruits[4])
print(fruits[5])

# apple
# banana
# pear
# strawberry
# cherry
# Traceback (most recent call last):
#   File "./test.py", line 7, in <module>
#     print(fruits[5])
# IndexError: list index out of range

리스트와 마찬가지로 튜플의 인덱스도 음수를 사용할 수 있다. 인덱스를 음수로 지정할 경우 뒤에서 몇 번째인지를 의미한다.

fruits = ('apple', 'banana', 'pear', 'strawberry', 'cherry')
print(fruits[-1])
print(fruits[-2])
print(fruits[-3])
print(fruits[-4])

# cherry
# strawberry
# pear
# banana

리스트와 마찬가지로 앞에서부터는 0,1,2,3으로 시작하지만 뒤에서부터는 -1, -2, -3 순으로 인덱싱된다.

리스트와 마찬가지로 복수 할당도 가능하다.

l = (1, 2, 3)
v1, v2, v3 = l

print(v1)
print(v2)
print(v3)

# 1
# 2
# 3

역시 리스트와 마찬가지로 튜플에 담겨있는 엘리먼트 개수와 복수할당에 사용한 변수의 개수가 맞아야 한다. 그렇지 않으면 ValueError가 발생한다.

l = (1, 2, 3)
v1, v2 = l

print(v1)
print(v2)

# Traceback (most recent call last):
#   File "./test.py", line 5, in <module>
#    v1, v2 = l
# ValueError: too many values to unpack (expected 2)

리스트와 마찬가지로 튜플의 엘리먼트로 또 다른 튜플을 사용할 수 있다. 이 경우 연속적인 대괄호를 이용해서 특정 값을 따라갈 수 있다. 예를 들어

fruits = ('apple', ('banana', 'cherry'), ('pear', 'strawberry'))

print(fruits[0])
print(fruits[1])
print(fruits[1][0])
print(fruits[1][1])
print(fruits[2])
print(fruits[2][0])
print(fruits[2][1])

# apple
# ('banana', 'cherry')
# banana
# cherry
# ('pear', 'strawberry')
# pear
# strawberry

fruits 튜플의 엘리먼트는 'apple', ('banana', 'cherry'), ('pear', 'strawberry') 이다. fruits[0]은 'apple'이고, fruits[1]은 ('banana', 'cherry')라는 튜플이다. 여기에서 'banana'를 접근하려면 한번더 인덱스를 이용해 fruits[1][0]으로 접근하면  된다.

튜플 수정

튜플은 리스트와 다르게 값을 수정할 수 없다. 값을 수정하려고 시도하면 TypeError가 발생한다.

fruits = ('apple', 'banana', 'pear', 'strawberry', 'cherry')
fruits[1] = 'mango'

print(fruits)

# Traceback (most recent call last):
#   File "./test.py", line 4, in <module>
#     fruits[1] = 'mango'
# TypeError: 'tuple' object does not support item assignment

당연하게도 이미 생성된 튜플에 엘리먼트를 추가하는 add, extend, append 같은 메소드는 제공되지 않으며, 엘리먼트를 삭제하는 del이나 remove 같은 함수와 메소드도 지원되지 않는다.

튜플에 엘리먼트를 추가하거나 삭제하려면 새로운 튜플을 만들면서 엘리먼트를 포함, 제외하는 방법 밖에 없다.

튜플 슬라이스

리스트와 마찬가지로 튜플에 있는 특정 범위 엘리먼트들을 슬라이스(slice)할 수 있다. 리스트와 동일하게 튜플도 인덱스 번호와 콜론(:) 문자를 이용해 사용한다.

예를 들어보자.

fruits = ('apple', 'banana', 'pear', 'strawberry', 'cherry')

print(fruits[1:3])
print(fruits[4:])
print(fruits[-3:-1])

# ('banana', 'pear')
# ('cherry',)
# ('pear', 'strawberry')

fruits[1:3]은 1번 인덱스부터 3번 인덱스 직전까지 엘리먼트를 잘라서 새로운 튜플로 만들어 준다. 콜론과 함께 오는 두 숫자들은 생략할 수 있다. 생략되었다면 끝까지라는 뜻으로 앞쪽 숫자가 생략되면 처음부터, 뒤쪽 숫자가 생략되면 끝까지라는 뜻이다. 

튜플 슬라이스에는 음수 인덱스도 사용할 수 있다. 음수 인덱스는 뒤에서부터 몇 번째까지 자르겠다는 의미로 해석할 수 있다. 예를 들어 [-4: -1]은 뒤에서부터 4번째 엘리먼트부터 뒤에서부터 첫 번째 엘리먼트직전까지 잘라내겠다는 의미로 해석하면 된다.

튜플의 슬라이스에서는 두 번째 인덱스에 해당하는 값은 포함되지 않음을 주의해야한다.

튜플 더하기 - tuple + tuple

리스트와 마찬가지로 두 개의 튜플을 더하면 두 튜플의 엘리먼트들을 이어 붙인 새로운 튜플이 생성된다.

my_fruits = ('apple', 'banana', 'pear')
your_fruits = ('strawberry', 'cherry')

fruits = my_fruits + your_fruits

print(fruits)

# ('apple', 'banana', 'pear', 'strawberry', 'cherry')

my_fruits 튜플과 your_fruits 튜플을 합쳐서 새로운 튜플 객체가 생성되었다. 이렇게 튜플의 엘리먼트를 변경하려면 새로운 튜플을 생성하는 수 밖에 없다.

튜플 곱하기 - tuple * n

튜플에 곱하기 연산을 하면 튜플의 엘리먼트를 n 번 반복하는 새로운 튜플을 만들어준다. 예를 들어 튜플에 2를 곱하면 튜플의 엘리먼트가 2번 반복되는 새로운 튜플이 생성된다.

my_fruits = ('apple', 'banana', 'pear')
fruits = my_fruits * 3
empty_fruits = my_fruits * 0

print(fruits)
print(empty_fruits)

# ('apple', 'banana', 'pear', 'apple', 'banana', 'pear', 'apple', 'banana', 'pear')
# ()

튜플 길이 구하기 - len

파이썬의 내장 함수인 len() 함수를 이용해서 튜플에 몇 개의 엘리먼트가 포함되어 있는지 확인할 수 있다. 즉, len(튜플)을 호출하면 튜플의 길이를 반환해준다.

fruits = ('apple', 'banana', 'pear', 'strawberry', 'cherry')

print(len(fruits))

# 5

특정 엘리먼트 개수 세기 - count()

튜플에는 같은 값을 갖는 엘리먼트가 중복 저장될 수 있다. 튜플은 count() 메소드를 통해 특정 값을 갖는 엘리먼트가 몇개 속해있는지 확인할 수 있게 해준다.

fruits = ('apple', 'banana', 'pear', 'strawberry', 'cherry', 'banana')

print(fruits.count('apple'))
print(fruits.count('banana'))

# 1
# 2

fruits 튜플에는 apple이 한개 banana가 두개 존재한다. 따라서 각각 1과 2를 리턴했다. 만약 튜플에 존재하지 않는 값을 count() 메소드의 인자로 줬다면  0이 리턴된다.

특정 엘리먼트의 인덱스 - index()

특정 값을 갖는 엘리먼트가 튜플의 몇 번째에 위치하는지를 index() 메소드를 통해 확인할 수 있다. index() 메소드의 인자로 넘긴 엘리먼트가 튜플의 몇 번째에 위치해있는지를 리턴한다.

fruits = ('apple', 'banana', 'pear', 'strawberry', 'cherry', 'banana')

print(fruits.index('apple'))
print(fruits.index('banana'))

# 0
# 1

만약 인자로 받은 값이 튜플에 두 개 이상 존재한다면 처음 등장하는 엘리먼트의 인덱스가 리턴된다.

만약 튜플에 존재하지 않는 값을 인자로 주면 ValueError가 발생한다. 

fruits = ('apple', 'banana', 'pear', 'strawberry', 'cherry', 'banana')

print(fruits.index('mango'))

# Traceback (most recent call last):
#   File "./test.py", line 3, in <module>
#     print(fruits.index('mango'))
# ValueError: 'mango' is not in list

튜플에 엘리먼트가 존재하는지 확인

리스트와 마찬가지로 튜플에 특정 값을 갖는 엘리먼트가 있는지 확인하는 방법으로 count() 메소드나 index() 메소드 말고 in (not in) 연산을 사용할 수 있다. 

'값 in 튜플'을 사용하면 값에 해당하는 엘리먼트가 튜플에 존재하는지를 조사해서 있으면 True, 없으면 False를 리턴한다. not in을 사용하면 그 반대로 없으면 True, 있으면 False를 리턴해준다. 이를 조건문의 조건으로 사용하는 경우가 많다.

fruits = ('apple', 'banana', 'pear', 'strawberry', 'cherry', 'banana')

if 'cherry' in fruits:
    print('체리는 fruits에 있음')

if 'mango' in fruits:
    print('망고는 fruits에 있음')
    
# 체리는 fruits에 있음

'cherry'라는 값의 엘리먼트는 fruits 튜플에 포함되어 있으므로 첫 번째 조건문이 True가 된다. 반면 'mango'는 없으므로 두 번째 조건문은 False가 된다.

in을 not in으로 바꾸면 예상한대로 반대의 결과가 나온다.

fruits = ('apple', 'banana', 'pear', 'strawberry', 'cherry', 'banana')

if 'cherry' not in fruits:
    print('체리는 fruits에 있음')

if 'mango' not in fruits:
    print('망고는 fruits에 있음')
    
 # 망고는 fruits에 있음

튜플 엘리먼트 순회

튜플에 포함되어 있는 엘리먼트들을 하나씩 순회하면서 어떤 작업을 하고 싶은 경우 for 문을 사용하면된다.

fruits = ('apple', 'banana', 'pear', 'strawberry', 'cherry', 'banana')

for f in fruits:
  print(f)
  
# apple
# banana
# pear
# strawberry
# cherry
# banana

 

파이썬 스크립트 작성에 도움되는 글 모음

파이썬으로 프로그램을 작성할 때 도움되는 글들을 모아본다. 개발환경 [Python] macOS에 파이참 설치 [Python] 파이참 깃허브 연동 [Python] 파이썬 PIP란? [Python] VSCode를 이용한 개발환경 [Python] python3..

hbase.tistory.com

 

[Python] 집합 (set) 자료형 사용법 및 예제

파이썬 2.3부터 '집합(set)' 자료형이 지원되기 시작했다. set은 집합과 관련된 연산들을 쉽게 처리하기 위해 제공하는 자료형이다. 특히 파이썬 프로그램에서 중복된 값을 제거하기 위해서 많이

hbase.tistory.com

 

[Python] 집합 (set) 자료형 사용법 및 예제

파이썬 2.3부터 '집합(set)' 자료형이 지원되기 시작했다. set은 집합과 관련된 연산들을 쉽게 처리하기 위해 제공하는 자료형이다. 특히 파이썬 프로그램에서 중복된 값을 제거하기 위해서 많이

hbase.tistory.com

 

[Python] 리스트(list) 자료형 사용법 및 예제

리스트는 일련의 데이터를 묶어서 같이 처리할 수 있게 해주는 자료형 중 하나다. 관련있는 데이터들을 하나의 리스트에 담아서 함께 처리하는 코드는 파이썬에서 굉장히 흔하게 사용된다. 이

hbase.tistory.com

 

댓글