Python 튜플

튜플이란?

  • 불변(immutable) 시퀀스 자료형
  • 요소의 추가, 수정, 삭제가 불가능
  • 리스트보다 메모리 효율적, 해시 가능 (딕셔너리 키로 사용 가능)

튜플 생성

t = (1, 2, 3)
t = 1, 2, 3              # 괄호 생략 가능
t = tuple([1, 2, 3])     # 리스트에서 변환
t = tuple("abc")         # ('a', 'b', 'c')

# 빈 튜플
t = ()
t = tuple()

# 요소 1개짜리 튜플 (쉼표 필수!)
t = (1,)                 # 튜플
t = (1)                  # int (괄호만 있으면 그냥 정수)

인덱싱과 슬라이싱

t = (0, 1, 2, 3, 4)

# 인덱싱 (리스트와 동일)
t[0]         # 0
t[-1]        # 4

# 슬라이싱
t[1:3]       # (1, 2)
t[::-1]      # (4, 3, 2, 1, 0) (역순)

튜플 연산

a = (1, 2)
b = (3, 4)

a + b        # (1, 2, 3, 4) - 연결
a * 3        # (1, 2, 1, 2, 1, 2) - 반복
len(a)       # 2 - 길이
2 in a       # True - 포함 여부

튜플 메서드

t = (1, 2, 3, 2, 4, 2)

t.count(2)   # 3 (2의 개수)
t.index(2)   # 1 (첫 번째 2의 인덱스)
t.index(2, 2) # 3 (인덱스 2부터 검색)

언패킹 (Unpacking)

# 기본 언패킹
t = (1, 2, 3)
a, b, c = t          # a=1, b=2, c=3

# 함수 반환값 언패킹
def get_info():
    return "Alice", 25, "Seoul"

name, age, city = get_info()

# 변수 교환 (swap)
a, b = 1, 2
a, b = b, a          # a=2, b=1

# * 연산자로 나머지 수집
a, *rest = (1, 2, 3, 4, 5)    # a=1, rest=[2, 3, 4, 5]
a, *mid, b = (1, 2, 3, 4, 5)  # a=1, mid=[2, 3, 4], b=5
*start, a = (1, 2, 3, 4, 5)   # start=[1, 2, 3, 4], a=5

# 무시할 값은 _로
a, _, c = (1, 2, 3)           # 2는 무시
a, *_ = (1, 2, 3, 4, 5)       # 나머지 무시

중첩 언패킹

# 중첩 튜플 언패킹
data = ("Alice", (25, "Seoul"))
name, (age, city) = data      # name="Alice", age=25, city="Seoul"

# for문에서 언패킹
pairs = [(1, "a"), (2, "b"), (3, "c")]
for num, char in pairs:
    print(num, char)

# enumerate와 함께
for i, (num, char) in enumerate(pairs):
    print(i, num, char)

네임드튜플 (namedtuple)

from collections import namedtuple

# 정의
Point = namedtuple("Point", ["x", "y"])
# 또는
Point = namedtuple("Point", "x y")

# 생성
p = Point(3, 4)
p = Point(x=3, y=4)

# 접근
p.x          # 3 (이름으로 접근)
p[0]         # 3 (인덱스로 접근)

# 언패킹
x, y = p

# 메서드
p._asdict()           # {'x': 3, 'y': 4}
p._replace(x=10)      # Point(x=10, y=4) (새 객체)
p._fields             # ('x', 'y')

# 기본값 설정 (Python 3.7+)
Point = namedtuple("Point", ["x", "y"], defaults=[0, 0])
Point()               # Point(x=0, y=0)

튜플 vs 리스트

특성튜플리스트
가변성불변 (immutable)가변 (mutable)
문법(1, 2, 3)[1, 2, 3]
메모리더 효율적덜 효율적
해시 가능O (딕셔너리 키 가능)X
용도고정 데이터, 반환값동적 데이터
# 튜플은 딕셔너리 키로 사용 가능
locations = {(0, 0): "origin", (1, 2): "point A"}

# 리스트는 불가능
# {[0, 0]: "origin"}  # TypeError!

유용한 패턴

# 여러 값 반환
def min_max(lst):
    return min(lst), max(lst)

lo, hi = min_max([3, 1, 4, 1, 5])

# 함수 인자로 튜플 언패킹
def greet(name, age):
    print(f"{name} is {age}")

data = ("Alice", 25)
greet(*data)               # * 로 언패킹

# zip으로 튜플 리스트 만들기
names = ["Alice", "Bob"]
ages = [25, 30]
list(zip(names, ages))     # [('Alice', 25), ('Bob', 30)]

# 딕셔너리 items()
d = {"a": 1, "b": 2}
for key, value in d.items():
    print(key, value)

# sorted로 튜플 정렬
data = [(3, "c"), (1, "a"), (2, "b")]
sorted(data)               # [(1, 'a'), (2, 'b'), (3, 'c')]
sorted(data, key=lambda x: x[1])  # 두 번째 요소 기준

# 불변 리스트가 필요할 때
CONSTANTS = (3.14, 2.71, 1.41)