파이썬 튜플 자료구조 이해하기

파이썬 튜플 자료구조 이해하기

튜플(tuple)이란 용어는 값의 유한한 순서의 배열을 설명하기 위해 사용 되는 수학적인 용어이다. 튜플은 요소가 순서대로 표시되기 때문에 순서가 지정되어 있다. 즉, (1, 2, 3)과 같은 튜플이 있을 때, 첫 번째 요소는 1이고 두 번째 요소는 2, 세 번째 요소는 3인 것이다. 파이썬에서는 수학적 개념인 튜플의 이름과 작성법을 빌려 사용한다.


튜플 생성하기

튜플 생성하는 방법 중 두 가지는 다음과 같다.
  1. 튜플 리터럴
  2. 내장 tuple() 함수

튜플 리터럴(Tuple Literal)

문자열 리터럴이 일부 텍스트를 따옴표로 묶어서 명시적으로 만든 문자열인 것처럼, 튜플 리터럴은 괄호로 묶고 쉼표로 구분된 값의 리스트 형식으로 명시적으로 작성된 튜플이다.

튜플 리터럴의 예시는 다음과 같다.

>>> my_first_tuple = (1, 2, 3)

정수 1, 2, 3을 담고 있는 튜플이 생성되고 my_first_tuple이라는 변수에 할당된다. 다음과 같이 type() 함수를 사용해 변수의 타입을 체크할 수 있다.

>>> type(my_first_tuple)
<class 'tuple'>

문자의 배열을 가진 문자열과는 다르게, 튜플은 어떤 종류의 값이라도 담을 수 있다. 예를 들어, (1, 2.0, "three")와 같이 다른 종류의 값을 가지고 있는 튜플 또한 유효하다.

빈 튜플 생성하기

파이썬에는 아무 값도 담고 있지 않은 특별한 튜플이 존재한다. 이 튜플은 빈 튜플(empty tuple)이라고 불리며 다음과 같이 아무 값 없이 빈 괄호로 생성할 수 있다.

>>> empty_tuple = ()

빈 튜플이 쓸모 없다고 생각이 들 수 있지만, 사실 상당히 실용적이다. 예를 들어, 짝수와 홀수인 정수를 모두 포함하는 튜플을 만들어야 한다고 가정해보자. 그런 정수는 존재하지 않지만, 빈 튜플을 생성함으로써 위와 같은 요청의 튜플을 제공할 수 있게 된다.

하나의 요소를 가진 튜플 생성하기

단 하나의 요소를 가진 튜플을 생성하려면 어떡해야할까? 다음 예제를 확인해보자.

>>> x = (1)
>>> type(x)
<class 'int'>

위 예제에서 보이는 것과 같이, 쉼표를 포함하지 않고 하나의 값을 괄호로 감싸주면, 파이썬에서는 그 값을 튜플로 해석하지 않고, 괄호 안의 값의 타입으로 해석한다. 그렇기 때문에 (1)의 타입이 정수인 것이다.

단일 값 1을 담고 있는 튜플을 생성하려면 다음과 같이 쉼표를 포함해야 한다.

>>> x = (1,)
>>> type(x)
<class 'tuple'>

내장 tuple() 함수

파이썬 내장 함수인 tuple() 함수를 사용해서 다른 타입의 시퀀스 자료형을 튜플로 생성할 수 있다.

>>> tuple("Python")
('P', 'y', 't', 'h', 'o', 'n')

tuple() 함수는 오직 하나의 매개변수만을 허용한다. 만약 값 들을 줄지어 전달한다면 파이썬은 TypeError를 일으킨다.

>>> tuple(1, 2, 3)
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
	tuple(1, 2, 3)
TypeError: tuple expected at most 1 arguments, got 3

만약 tuple() 함수에 인수로 전달된 값이 목록으로 해석될 수 없을 때 또한 TypeError가 발생한다.

>>> tuple(1)
Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
	tuple(1)
TypeError: 'int' object is not iterable

에러 메시지 안에 이터러블(iterable)이란 단어는 단일 정수 값 1이 반복될(iterated) 수 없다는 것이다. 즉, 정수 자료형에 하나씩 접근할 다수의 값을 포함하지 않고 있다는 것이다.

tuple() 함수에 매개변수는 선택적이다. 매개변수를 비어두면 빈 튜플을 생성한다.

>>> tuple()
()

튜플과 문자열의 유사점

튜플과 문자열은 많은 공통점을 가진다. 둘 다 유한한 길이를 가진 시퀀스 자료형이며, 인덱싱과 슬라이싱을 지원하고, 불변객체이며, 반복문 안에서 반복될 수 있다.

튜플과 문자열 사이의 가장 큰 차이점은, 튜플의 요소들은 어떤 종류의 값이라도 될 수 있다는 것이다. 반면에 문자열은 문자밖에 담아내지 못한다. 튜플과 문자열의 유사점을 더 자세히 알아보도록 하자.

튜플은 길이를 가진다

튜플과 문자열 둘 다 길이(length)를 가진다. 문자열의 길이는 문자열 안 문자의 수이지만, 튜플의 길이는 튜플이 담고 있는 요소의 수다.

>>> numbers = (1, 2, 3)
>>> len(numbers)
3

튜플은 인덱싱과 슬라이싱을 지원한다

튜플은 문자열과 마찬가지로 인덱싱과 슬라이싱을 지원한다. 사용 방법을 동일하며 예제는 다음과 같다.

인덱싱
# 문자열
>>> name = "Jacob"
>>> name[1]
'a'

# 튜플
>>> values = (1, 3, 5, 7, 9)
>>> values[2]
5
슬라이싱
# 문자열
>>> name = "Jacob"
>>> name[2:4]
"co"

# 튜플
>>> values = (1, 3, 5, 7, 9)
>>> values[2:4]
(5, 7)

튜플은 불변객체이다

문자열과 마찬가지로 튜플은 불변객체이다. 즉, 튜플이 생성되고 나서 튜플 안에 요소의 값을 변경할 수 없다는 것이다. 만약 튜플의 값을 변경하려고 시도한다면, 파이썬은 TypeError를 일으킨다.

>>> values[0] = 2
Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
	values[0] = 2
TypeError: 'tuple' object does not support item assignment

튜플은 반복이 가능하다

튜플도 문자열처럼 반복문 안에서 반복이 가능하다.

>>> vowels = ("a", "e", "i", "o", "u")
>>> for vowel in vowels:
... print(vowel.upper())
...
A
E
I
O
U

튜플 패킹과 언패킹

튜플을 생성하는 또 다른 방법이 존재하는데 바로 패킹(packing)이라고 불리는 방법이다. 값 들의 목록을 쉼표로 나누고 괄호 없이 사용할 수 있다.

>>> coordinates = 4.21, 9.29
>>> type(coordinates)
<class 'tuple'>

위 예제를 보면, 두 가지의 값이 coordinates라는 하나의 변수에 할당된 것처럼 보인다. 어떤 의미에서는 맞는 말이지만, 그러나 결과는 두 가지 값 모두 하나의 튜플에 패킹되었다.

튜플에 값을 패킹할 수 있으면, 반대로 언패킹도 당연히 가능해야 할 것이다.

>>> x, y = coordinates
>>> x
4.21
>>> y
9.29

coordinates라는 단일 튜플에 담긴 값들이 두 개의 다른 변수 xy에 언패킹되었다. 튜플 패킹과 언패킹을 합쳐 사용함으로써, 다수의 변수 할당을 한줄로 작성할 수 있다.

>>> name, age, occupation = "David", 34, "programmer"
>>> name
'David'
>>> age
34
>>> occupation
'programmer'
한 줄에 여러 개의 변수에 할당함으로 프로그램을 짧게 작성할 수는 있지만, 한 줄에 너무 많은 값을 할당하는 것은 자제해야 한다.
이런식으로 두 개나 세 개 이상의 변수에 할당하는 것은 어떤 값이 어떤 변수 이름에 할당 되었는지 구분하기 어려워진다.

한 가지 조심해야 할 부분은, 튜플 형태의 값의 수가 변수의 이름의 수와 동일하지 않으면 파이썬은 ValueError를 일으킨다.

>>> a, b, c, d = 1, 2, 3
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
	a, b, c, d = 1, 2, 3
ValueError: not enough values to unpack (expected 4, got 3)

반대 상황도 마찬가지로 에러를 발생한다.

>>> a, b, c = 1, 2, 3, 4
Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
	a, b, c = 1, 2, 3, 4
ValueError: too many values to unpack (expected 3)

튜플 활용하기

튜플 값 존재 여부 확인

in 키워드를 사용하면 특정 값이 튜플에 존재하는지 확인할 수 있다. 특정 값이 존재하면 True, 없으면 False를 반환한다.

>>> vowels = ("a", "e", "i", "o", "u")
>>> "o" in vowels
True
>>> "x" in vowels
False

함수로부터 다수의 값 반환하기

튜플이 흔히 사용되는 방법 중 하나가 바로 단일 함수에서 여러 개의 값을 반환하는 것이다. 다음 예제처럼, 리턴문에서 튜플을 사용함으써 여러 값을 반환할 수 있다.

>>> def adder_subtractor(num1, num2):
... 	return (num1 + num2, num1 - num2)
...
>>> adder_subtractor(3, 2)
(5, 1)

Reference