본문 바로가기
C.W.K.
Stream
Lesson 03 of 07 · published

튜플 — 바뀌지 않는 순서와 언패킹

~20 min · tuple, immutable, unpacking, namedtuple

Level 0호기심
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete

쉼표가 만드는 고정된 묶음

튜플은 순서가 있지만 만든 뒤 원소를 바꿀 수 없는 시퀀스야. 괄호보다 쉼표가 핵심이라 원소 하나짜리 튜플은 (value,)처럼 써야 해. 함수가 여러 값을 돌려주는 것처럼 보일 때도 실제로는 튜플을 돌려주고 언패킹하는 경우가 많아.

모양을 한 번에 풀어 받기

a, b = pair처럼 위치에 맞춰 이름을 붙이고, 별표 이름으로 가운데 여러 값을 받을 수 있어. 순서와 개수가 계약인 작은 레코드에 잘 어울리지만, 필드가 많아지면 이름이 있는 형태가 더 안전해.

불변과 해시 가능은 같은 말이 아니야

튜플 자체는 원소를 갈아 끼울 수 없지만 안에 리스트가 있으면 그 리스트는 바뀔 수 있어. 딕셔너리 키나 집합 원소가 되려면 튜플 안의 모든 값도 해시 가능해야 해.

namedtuple로 위치에 이름 붙이기

namedtuple은 튜플의 작은 크기와 언패킹을 유지하면서 point.x처럼 필드 이름으로 읽게 해. 기본값·검증·행동이 많아지면 dataclass가 더 알맞아.

Code

튜플과 원소 하나짜리 튜플·python
# 모두 tuple — 콤마가 진짜 연산자
empty = ()
single = (1,)              # 끝 콤마 필수
pair = 1, 2                # 괄호 옵션
triple = (1, 2, 3)
mixed = "a", 1, [2, 3]     # tuple 안에 뭐든

# 끝 콤마 없으면 그냥 괄호 친 식
not_a_tuple = (1)
print(type(not_a_tuple))   # <class 'int'>
print(type(single))        # <class 'tuple'>

# tuple() 생성자 — 어떤 iterable 도
t = tuple("abc")
print(t)                   # ('a', 'b', 'c')
언패킹과 별표로 여러 값 받기·python
# 다중 할당
x, y, z = 1, 2, 3

# swap
a, b = 10, 20
a, b = b, a
print(a, b)                # 20 10

# 여러 값 반환하는 함수도 사실 tuple 반환
def divmod_(a, b):
    return a // b, a % b

q, r = divmod_(17, 5)
print(q, r)                # 3 2

# star-unpacking — 나머지 잡기
first, *middle, last = [1, 2, 3, 4, 5]
print(first, middle, last) # 1 [2, 3, 4] 5
해시 가능한 튜플만 키가 된다·python
# hashable 한 것들의 tuple 은 hashable
grid = {}
grid[(0, 0)] = "start"
grid[(3, 4)] = "goal"
print(grid[(3, 4)])         # 'goal'

# list 가 들어간 tuple 은 hashable 하지 않음
bad_key = (1, [2, 3])
try:
    grid[bad_key] = "oops"
except TypeError as e:
    print("실패:", e)        # unhashable type: 'list'
튜플 안의 가변 객체·python
t = ([1, 2], 3)

# t[0] 자체는 재할당 불가
try:
    t[0] = [99]
except TypeError as e:
    print(e)                # 'tuple' object does not support item assignment

# 근데 t[0] 이 가리키는 객체는 mutable
t[0].append(99)
print(t)                    # ([1, 2, 99], 3)

# 그래서 이 tuple 은 hashable 도 아님 — 안의 list 가 깨
try:
    hash(t)
except TypeError as e:
    print(e)                # unhashable type: 'list'
필드 이름이 있는 namedtuple·python
from collections import namedtuple

Point = namedtuple("Point", ["x", "y"])
p = Point(3, 4)

print(p.x, p.y)             # 3 4    — 이름 접근
print(p[0], p[1])           # 3 4    — 인덱싱도 됨

x, y = p                    # unpacking 도 됨
print(x, y)                 # 3 4

# 불변
try:
    p.x = 99
except AttributeError as e:
    print(e)                # can't set attribute

# _replace — 새 namedtuple 반환
p2 = p._replace(x=10)
print(p2)                   # Point(x=10, y=4)

External links

Exercise

ticker, price, shares 필드를 가진 Stock namedtuple을 정의하고 세 종목을 만들어. 각 보유 가치와 가치 내림차순 결과를 구한 뒤, _replace로 한 종목의 가격이 10% 낮아진 새 튜플을 만들어. 원본이 바뀌지 않았는지도 확인해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.