안녕하세요! 지난 시간에는 파이썬의 가장 유용하고 유연한 자료구조인 리스트(List)에 대해 자세히 알아보았습니다. 리스트는 순서가 있고, 다양한 자료형을 저장할 수 있으며, 무엇보다 내용을 자유롭게 변경(추가, 삭제, 수정)할 수 있는 특징이 있었죠.
이번 시간에는 리스트와 매우 비슷하게 여러 데이터를 순서대로 담지만, 결정적인 차이를 가진 또 다른 자료구조인 **튜플(Tuple)**에 대해 알아보겠습니다. 튜플의 가장 중요한 특징은 바로 **불변성(Immutability)**입니다.
"불변성"이 무엇인지, 그리고 튜플은 어떤 상황에 사용되는지 함께 살펴볼까요?
Part 1: 튜플(Tuple)이란 무엇인가?
파이썬의 튜플은 다음과 같은 특징을 가집니다.
- 순서가 있다: 리스트와 마찬가지로 데이터를 저장한 순서가 유지됩니다. 따라서 인덱스를 사용하여 특정 위치의 데이터에 접근할 수 있습니다.
- 다양한 자료형 저장 가능: 하나의 튜플 안에 정수, 실수, 문자열, 심지어 다른 리스트나 튜플까지! 어떤 자료형의 데이터든 함께 저장할 수 있습니다.
- 변경 불가능하다 (Immutable): 이것이 리스트와 튜플의 가장 큰 차이점입니다. 한 번 튜플을 만들면 그 안에 있는 요소를 추가, 삭제, 변경할 수 없습니다.
- 중복 허용: 같은 값을 여러 번 저장할 수 있습니다.
1. 튜플 만들기
튜플은 괄호(()) 안에 쉼표(,)로 구분하여 요소들을 나열하는 방식으로 만듭니다. 괄호를 생략하고 쉼표만으로도 튜플을 만들 수 있습니다.
예시:
# 파일 이름: tuple_creation.py
# 다양한 자료형을 포함하는 튜플
my_tuple = (1, 2, "hello", 3.14, True)
fruits_tuple = ("사과", "바나나", "체리", "사과") # 중복 허용
# 괄호 없이 쉼표로만 튜플 생성 (권장되지 않으나 가능)
coordinates = 10, 20, 30
# 요소가 하나인 튜플 만들기 (쉼표가 중요!)
single_element_tuple = (5,) # 괄호 안에 요소 하나만 있고 쉼표가 있어야 튜플로 인식
not_a_tuple = (5) # 괄호만 있으면 그냥 5 (정수)로 인식
# 빈 튜플
empty_tuple = ()
print(f"my_tuple: {my_tuple}, 타입: {type(my_tuple)}")
print(f"fruits_tuple: {fruits_tuple}, 타입: {type(fruits_tuple)}")
print(f"coordinates: {coordinates}, 타입: {type(coordinates)}")
print(f"single_element_tuple: {single_element_tuple}, 타입: {type(single_element_tuple)}")
print(f"not_a_tuple: {not_a_tuple}, 타입: {type(not_a_tuple)}") # int로 출력됨
print(f"empty_tuple: {empty_tuple}, 타입: {type(empty_tuple)}")
# 파일 이름: tuple_creation.py
# 다양한 자료형을 포함하는 튜플
my_tuple = (1, 2, "hello", 3.14, True)
fruits_tuple = ("사과", "바나나", "체리", "사과") # 중복 허용
# 괄호 없이 쉼표로만 튜플 생성 (권장되지 않으나 가능)
coordinates = 10, 20, 30
# 요소가 하나인 튜플 만들기 (쉼표가 중요!)
single_element_tuple = (5,) # 괄호 안에 요소 하나만 있고 쉼표가 있어야 튜플로 인식
not_a_tuple = (5) # 괄호만 있으면 그냥 5 (정수)로 인식
# 빈 튜플
empty_tuple = ()
print(f"my_tuple: {my_tuple}, 타입: {type(my_tuple)}")
print(f"fruits_tuple: {fruits_tuple}, 타입: {type(fruits_tuple)}")
print(f"coordinates: {coordinates}, 타입: {type(coordinates)}")
print(f"single_element_tuple: {single_element_tuple}, 타입: {type(single_element_tuple)}")
print(f"not_a_tuple: {not_a_tuple}, 타입: {type(not_a_tuple)}")
print(f"empty_tuple: {empty_tuple}, 타입: {type(empty_tuple)}")
[VS Code 터미널 출력]

Part 2: 튜플 요소 접근하기 - 인덱싱(Indexing) 및 슬라이싱(Slicing)
튜플도 리스트와 마찬가지로 순서가 있는 자료구조이기 때문에, 인덱싱과 슬라이싱을 통해 요소에 접근할 수 있습니다.
- 인덱싱: 대괄호 [] 안에 인덱스 번호를 넣어 특정 위치의 요소를 가져옵니다. (0부터 시작, 음수 인덱스 가능)
- 슬라이싱: 콜론 :을 사용하여 튜플의 특정 부분(범위)을 잘라내어 새로운 튜플을 만듭니다.
1. 인덱싱으로 요소 접근
예시:
# 파일 이름: tuple_indexing.py
coordinates = (10, 20, 30, 40, 50)
# 양수 인덱스
print(f"첫 번째 요소 (인덱스 0): {coordinates[0]}")
print(f"세 번째 요소 (인덱스 2): {coordinates[2]}")
# 음수 인덱스
print(f"마지막 요소 (인덱스 -1): {coordinates[-1]}")
print(f"뒤에서 세 번째 요소 (인덱스 -3): {coordinates[-3]}")
# 파일 이름: tuple_indexing.py
coordinates = (10, 20, 30, 40, 50)
# 양수 인덱스
print(f"첫 번째 요소 (인덱스 0): {coordinates[0]}")
print(f"세 번째 요소 (인덱스 2): {coordinates[2]}")
# 음수 인덱스
print(f"마지막 요소 (인덱스 -1): {coordinates[-1]}")
print(f"뒤에서 세 번째 요소 (인덱스 -3): {coordinates[-3]}")
[VS Code 터미널 출력]

2. 슬라이싱으로 부분 튜플 가져오기
예시:
# 파일 이름: tuple_slicing.py
numbers_tuple = (10, 20, 30, 40, 50, 60, 70)
# 인덱스 1부터 4까지 (인덱스 4 미포함)
slice1 = numbers_tuple[1:5]
print(f"numbers_tuple[1:5]: {slice1}") # (20, 30, 40, 50)
# 처음부터 인덱스 3까지 (인덱스 3 미포함)
slice2 = numbers_tuple[:3]
print(f"numbers_tuple[:3]: {slice2}") # (10, 20, 30)
# 인덱스 4부터 끝까지
slice3 = numbers_tuple[4:]
print(f"numbers_tuple[4:]: {slice3}") # (50, 60, 70)
# 전체 튜플 복사
slice4 = numbers_tuple[:]
print(f"numbers_tuple[:]: {slice4}") # (10, 20, 30, 40, 50, 60, 70)
# 파일 이름: tuple_slicing.py
numbers_tuple = (10, 20, 30, 40, 50, 60, 70)
# 인덱스 1부터 4까지 (인덱스 4 미포함)
slice1 = numbers_tuple[1:5]
print(f"numbers_tuple[1:5]: {slice1}")
# 처음부터 인덱스 3까지 (인덱스 3 미포함)
slice2 = numbers_tuple[:3]
print(f"numbers_tuple[:3]: {slice2}")
# 인덱스 4부터 끝까지
slice3 = numbers_tuple[4:]
print(f"numbers_tuple[4:]: {slice3}")
# 전체 튜플 복사
slice4 = numbers_tuple[:]
print(f"numbers_tuple[:]: {slice4}")
[VS Code 터미널 출력]

Part 3: 튜플의 불변성 (Immutability) - 가장 중요한 특징!
튜플은 한 번 생성되면 그 요소를 변경(수정, 추가, 삭제)할 수 없습니다. 이 특징을 **불변성(Immutability)**이라고 합니다.
1. 불변성으로 인한 오류 확인
예시:
# 파일 이름: tuple_immutability.py
my_tuple = (10, 20, 30)
print(f"원본 튜플: {my_tuple}")
# 튜플 요소 변경 시도 (오류 발생!)
# my_tuple[0] = 5 # TypeError: 'tuple' object does not support item assignment
# 튜플에 요소 추가 시도 (오류 발생!)
# my_tuple.append(40) # AttributeError: 'tuple' object has no attribute 'append'
# 튜플 요소 삭제 시도 (오류 발생!)
# del my_tuple[0] # TypeError: 'tuple' object doesn't support item deletion
print("튜플은 한 번 생성되면 요소를 변경할 수 없습니다.")
# 파일 이름: tuple_immutability.py
my_tuple = (10, 20, 30)
print(f"원본 튜플: {my_tuple}")
# 튜플 요소 변경 시도 (오류 발생!)
# my_tuple[0] = 5 # TypeError: 'tuple' object does not support item assignment
# 튜플에 요소 추가 시도 (오류 발생!)
# my_tuple.append(40) # AttributeError: 'tuple' object has no attribute 'append'
# 튜플 요소 삭제 시도 (오류 발생!)
# del my_tuple[0] # TypeError: 'tuple' object doesn't support item deletion
print("튜플은 한 번 생성되면 요소를 변경할 수 없습니다.")
[VS Code 터미널 출력 (오류 발생 시)]

(위 오류는 my_tuple[0] = 5 주석을 해제하고 실행했을 때 발생하는 예시입니다.)
2. 튜플 안에 '변경 가능한' 객체가 있을 경우 (주의!)
튜플 자체가 불변이라는 것은 튜플의 '요소'를 변경할 수 없다는 의미입니다. 하지만 튜플 안에 리스트처럼 '변경 가능한(mutable)' 객체가 들어있다면, 그 변경 가능한 객체 내부의 내용은 변경할 수 있습니다.
예시:
# 파일 이름: tuple_mutable_element_caution.py
# 튜플 안에 리스트가 요소로 들어있는 경우
my_data = (1, [2, 3], 4)
print(f"원본 튜플: {my_data}")
# 튜플의 두 번째 요소(리스트)에 접근하여 리스트 내부의 요소 변경
my_data[1][0] = 99
print(f"리스트 내부 변경 후: {my_data}") # (1, [99, 3], 4)
# 튜플의 요소를 완전히 교체하는 것은 불가능
# my_data[1] = [5, 6] # TypeError 발생
# 파일 이름: tuple_mutable_element_caution.py
# 튜플 안에 리스트가 요소로 들어있는 경우
my_data = (1, [2, 3], 4)
print(f"원본 튜플: {my_data}")
# 튜플의 두 번째 요소(리스트)에 접근하여 리스트 내부의 요소 변경
my_data[1][0] = 99
print(f"리스트 내부 변경 후: {my_data}")
# 튜플의 요소를 완전히 교체하는 것은 불가능
# my_data[1] = [5, 6] # TypeError 발생
[VS Code 터미널 출력]

Part 4: 튜플은 언제 사용해야 할까? (리스트와의 비교)
튜플과 리스트는 유사해 보이지만, 불변성이라는 중요한 차이 때문에 사용되는 목적이 다릅니다.
변경 가능성 | 변경 가능 (Mutable) | 변경 불가능 (Immutable) |
괄호 | 대괄호 [] | 괄호 () 또는 생략 |
용도 | - 요소의 추가/삭제/변경이 잦은 데이터- 동적으로 크기가 변하는 컬렉션 | - 변하면 안 되는 고정된 데이터 - 함수의 인자로 데이터를 전달할 때 (의도치 않은 변경 방지) - 딕셔너리의 키로 사용 (리스트는 안 됨) - 프로그램 실행 속도 면에서 리스트보다 약간 빠름 |
예시 | [1, 2, 3], ['apple', 'banana'] | (10, 20, 30), (3.14, '파이') |
튜플을 사용하는 주요 상황:
- 좌표 값: (x, y) 또는 (경도, 위도)처럼 여러 개의 고정된 값을 하나의 묶음으로 표현할 때.
- 색상 값: (빨강, 초록, 파랑) RGB 값처럼 고정된 순서와 의미를 가진 값들.
- 함수의 반환 값: 함수에서 여러 값을 묶어서 반환할 때.
- 딕셔너리의 키: 변경될 수 없는 값만이 딕셔너리의 키가 될 수 있는데, 튜플은 불변이라 키로 사용 가능합니다. (딕셔너리는 다음 포스팅에서 배울 거예요!)
마무리하며
이번 시간에는 파이썬의 중요한 자료구조 중 하나인 **튜플(Tuple)**에 대해 알아보았습니다. 튜플은 리스트와 유사하게 여러 데이터를 순서대로 담지만, **한 번 생성되면 내용을 변경할 수 없는 불변성(Immutable)**이라는 핵심 특징을 가집니다.
이 불변성 덕분에 튜플은 '변하면 안 되는 고정된 데이터'를 표현하거나, 데이터의 안정성을 확보해야 할 때 유용하게 사용됩니다. 리스트와 튜플의 차이점을 명확히 이해하고 적절한 상황에 사용하는 것이 중요합니다.
다음 포스팅에서는 '키(Key)'와 '값(Value)' 쌍으로 데이터를 저장하는 강력한 자료구조인 **딕셔너리(Dictionary)**에 대해 자세히 알아보겠습니다.
궁금한 점이 있다면 언제든지 질문해주세요! 다음 포스팅에서 만나요!
'Python' 카테고리의 다른 글
3-4. 세트(Set)의 특성과 중복 제거 (0) | 2025.06.24 |
---|---|
3-3. 딕셔너리(Dictionary)의 개념과 키-값 구조 (0) | 2025.06.23 |
3-1. 리스트(List)의 정의와 사용 (1) | 2025.06.23 |
2-6. 중첩 조건문과 반복문 활용 (0) | 2025.06.22 |
2-5. break, continue의 사용법 (0) | 2025.06.22 |