지식
Python
튜플: 불변 시퀀스의 힘과 언패킹 패턴
Python tuple의 생성·불변성·해시 가능성을 이해하고, 언패킹·스왑·namedtuple 활용까지 실전 패턴을 정리합니다.
지난 글에서 가변 시퀀스인 리스트를 살펴봤다. 이번에는 불변 시퀀스인 튜플(tuple)을 다룬다. 리스트와 비슷해 보이지만 불변성이 가져다주는 장점이 크다.
튜플 생성
t = (1, 2, 3) # 괄호 사용
t2 = 1, 2, 3 # 괄호 생략 가능
single = (1,) # 원소 1개: 쉼표 필수!
wrong = (1) # 이건 int 1 (튜플 아님)
empty = ()
원소가 하나인 튜플을 만들 때 쉼표를 빠뜨리는 실수가 흔하다. type((1)) 은 <class 'int'>다.
불변성과 해시
튜플은 수정 불가다. 이 덕분에 해시 가능하며, dict 키나 set 원소로 쓸 수 있다.
t = (1, 2, 3)
t[0] = 99 # TypeError: 'tuple' object does not support item assignment
# dict 키로 활용 (좌표, 복합 키 등)
grid = {(0, 0): "start", (3, 4): "end"}
visited = {(1, 2), (3, 4)}
단, 튜플이 가변 객체를 담고 있으면 해시 불가다.
hash((1, 2)) # 정상
hash(([1, 2],)) # TypeError: unhashable type: 'list'
언패킹
튜플의 가장 강력한 기능이다. 리스트나 모든 이터러블에도 동일하게 적용된다.
x, y, z = (10, 20, 30)
# 변수 스왑 (임시 변수 불필요)
a, b = 1, 2
a, b = b, a # a=2, b=1
# 별표(*) 언패킹
first, *rest = (1, 2, 3, 4, 5)
# first=1, rest=[2, 3, 4, 5]
head, *middle, tail = (1, 2, 3, 4, 5)
# head=1, middle=[2,3,4], tail=5
# 중첩 언패킹
(a, b), c = (1, 2), 3
for 루프에서의 언패킹
pairs = [(1, "one"), (2, "two"), (3, "three")]
for num, name in pairs:
print(f"{num}: {name}")
# enumerate, zip 결과도 동일
for i, val in enumerate(["a", "b", "c"]):
print(i, val)
함수의 다중 반환값
Python 함수는 튜플로 여러 값을 반환한다.
def min_max(lst):
return min(lst), max(lst) # tuple 반환
lo, hi = min_max([3, 1, 4, 1, 5])
result = min_max([3, 1, 4, 1, 5]) # tuple로 받기도 가능
namedtuple
필드에 이름을 붙이고 싶을 때 쓴다. 튜플의 모든 성질을 그대로 유지한다.
from collections import namedtuple
Point = namedtuple("Point", ["x", "y"])
p = Point(3, 4)
p.x, p.y # 3, 4 (이름으로 접근)
p[0], p[1] # 3, 4 (인덱스로도 접근)
x, y = p # 언패킹
# 특정 필드만 바꾼 새 인스턴스
p2 = p._replace(x=10) # Point(x=10, y=4)
Python 3.6+에서는 타입 힌트와 함께 사용하기 좋은 NamedTuple 클래스 방식도 있다.
from typing import NamedTuple
class Point(NamedTuple):
x: float
y: float
z: float = 0.0 # 기본값 가능
p = Point(1.0, 2.0)
리스트 vs 튜플 선택 기준
| 상황 | 선택 |
|---|---|
| 내용이 바뀌지 않는 레코드 | tuple |
| dict 키, set 원소 | tuple |
| 함수에서 여러 값 반환 | tuple |
| 동적으로 추가/삭제 필요 | list |
| 동질한 타입의 시퀀스 | list |
지난 글: 리스트 기초: Python의 만능 순서형 자료구조
다음 글: 딕셔너리 기초: 키-값 매핑의 모든 것
읽어주셔서 감사합니다. 😊