파이썬 튜플(Tuple)과 불변성, 리스트와 뭐가 다를까?

in #python • yesterday

튜플은 왜 수정이 안 될까?

지난 글에서는 여러 값을 담아 두고 필요에 따라 수정할 수 있는 리스트(List)를 살펴봤어요. 이번에는 리스트와 닮았지만 중요한 차이가 있는 튜플(Tuple)을 알아볼게요. 바로 만든 뒤에는 요소를 바꿀 수 없다는 점입니다. 처음엔 “그럼 굳이 왜 써?” 싶을 수 있는데요. 값이 바뀌면 곤란한 상황에서는 이 성질이 꽤 든든합니다.

튜플은 어떤 자료형일까?

괄호로 여러 값을 묶은 튜플과 요소의 순서
튜플은 여러 값을 순서대로 담는 자료형이에요. 리스트처럼 값마다 자리가 있고, 순서대로 꺼내 쓸 수 있습니다. 보통 소괄호 ()로 만들죠.

point = (3, 7)
colors = ("빨강", "초록", "파랑")

print(point[0])  # 3
print(colors[1]) # 초록

리스트에서처럼 인덱스는 0부터 시작하고, 슬라이싱도 할 수 있어요. 그래서 값을 읽고 다루는 모습은 익숙합니다. 다른 점은 요소를 추가하거나 바꾸거나 지울 수 없다는 것이에요.

point[0] = 5  # TypeError

이 코드는 오류가 납니다. 튜플은 처음 정한 요소를 그대로 유지하기 때문이에요. “수정이 안 된다”는 규칙을 꼭 기억해 두면, 튜플을 언제 고르면 좋을지 감이 옵니다.

리스트와 튜플, 언제 다를까?

리스트와 튜플의 수정 가능 여부 비교
리스트와 튜플은 둘 다 여러 값을 순서대로 보관하지만, 값이 바뀔 가능성을 다르게 다룹니다. 내가 수시로 내용을 바꿀 목록을 만들고 있다면 리스트가 자연스럽고, 정해진 값을 한 묶음으로 전달하거나 보관한다면 튜플이 잘 맞아요.

구분리스트튜플
표기대괄호 []소괄호 ()
요소 수정가능불가능
어울리는 경우바뀌는 할 일 목록고정된 좌표나 설정값

예를 들어 장바구니에 담긴 물건은 추가하거나 뺄 수 있으니 리스트가 편합니다. 반면 화면의 한 지점을 나타내는 (x, y) 좌표는 정해진 한 쌍으로 다루고 싶을 수 있죠. 꼭 정답이 있는 건 아니고, 값이 바뀌어야 하는지를 먼저 생각하면 선택하기 쉬워요.

튜플 만들 때 놓치기 쉬운 쉼표

한 요소 튜플에 꼭 필요한 쉼표
여기서 초보자들이 종종 헷갈리는 부분이 하나 있어요. 요소가 하나뿐인 튜플은 괄호만으로 만들 수 없습니다. 쉼표가 있어야 튜플로 인식돼요.

not_a_tuple = (5)
one_item_tuple = (5,)

print(type(not_a_tuple))     # <class 'int'>
print(type(one_item_tuple))  # <class 'tuple'>

(5)는 숫자 5를 괄호로 감싼 표현이고, (5,)가 튜플입니다. 쉼표 하나가 결과를 바꾸는 셈이죠. 괄호를 생략하고 쉼표로 값을 묶는 것도 가능해요.

rgb = 255, 128, 0
print(type(rgb))  # <class 'tuple'>

그래도 처음엔 괄호를 적는 편이 읽기 쉬워요. 코드가 짧아도 다음에 보는 사람이 편한 게 좋으니까요. 저도 예전에 쉼표를 빼먹고 타입을 확인하느라 잠깐 헤맸습니다. 음... 파이썬이 괄호보다 쉼표를 더 중요하게 보는 경우가 있더라고요.

불변성이 주는 장점과 주의점

튜플을 다룰 때 기억할 점 체크리스트
튜플이 불변이라는 건 값이 바뀌지 않도록 약속하는 것과 비슷해요. 좌표, 색상 값, 함수에서 함께 돌려주는 여러 결과처럼 한 묶음의 내용이 유지되길 바랄 때 유용합니다. 실수로 요소를 바꿔 버리는 일을 막아 주고, 코드를 읽는 사람에게도 “이 값은 바뀌지 않는구나”라는 신호를 줍니다.

다만 여기서 작은 함정이 있어요. 튜플 안에 리스트처럼 수정 가능한 자료형을 넣으면, 튜플의 자리는 그대로여도 그 안의 리스트 내용은 바뀔 수 있습니다.

items = (["사과", "배"], "과일")
items[0].append("귤")

print(items)  # (['사과', '배', '귤'], '과일')

튜플의 첫 번째 요소를 다른 리스트로 바꾼 건 아니지만, 그 요소가 가리키는 리스트를 수정한 거예요. 그래서 “튜플 안은 무조건 전부 못 바꾼다”고 이해하면 조금 부정확합니다. 튜플의 요소 자리는 바꿀 수 없고, 그 안에 든 객체의 성질은 따로 살펴야 한다고 기억하면 돼요.

또 튜플이라고 해서 언제나 딕셔너리의 키로 쓸 수 있는 것도 아닙니다. 키로 쓰려면 튜플 안의 값들도 해시 가능한, 쉽게 말해 안정적으로 식별할 수 있는 값이어야 해요. 숫자나 문자열만 든 튜플은 보통 키로 쓸 수 있지만, 리스트가 들어 있으면 키로 쓸 수 없습니다. 처음에는 이 규칙을 전부 외우기보다, 값이 고정되어야 할 때 튜플을 고려하는 것부터 익혀도 충분해요.

튜플은 값이 고정된 묶음에

리스트와 튜플을 고르는 기준은 어렵지 않습니다. 내용을 바꿀 계획이 있다면 리스트, 정해진 값을 한 묶음으로 유지하고 싶다면 튜플을 떠올려 보세요. 튜플도 인덱스로 읽을 수 있고, 여러 값을 한꺼번에 다루는 데 쓸 수 있습니다. 다만 요소를 직접 바꾸는 메서드는 없어요.

간단히 정리하면 이렇습니다.

  • 리스트: 추가·수정·삭제가 필요한 값 모음
  • 튜플: 정해진 순서와 값을 유지하고 싶은 묶음
  • 요소가 하나인 튜플: (값,)처럼 쉼표를 붙이기

이번에는 “값을 고정하는 방법”을 봤으니, 다음 글에서는 값에 이름을 붙여 저장하는 딕셔너리(Dictionary)를 살펴볼게요. 튜플이 순서와 위치를 기준으로 값을 찾는다면, 딕셔너리는 이름표 같은 키로 값을 찾습니다. 목록에서 이름으로 바로 꺼내는 느낌이라 처음엔 꽤 편할 거예요.

(html comment removed: aistudio:footer )

AIWD 소모임AI 자동화 오픈톡

원문: https://aiwd.kro.kr/autoblog/post/369