[파이썬 100강] 06강. 리스트와 튜플 핵심 사용법
리스트와 튜플은 파이썬에서 가장 자주 만나는 시퀀스 자료구조입니다. 둘 다 여러 값을 순서대로 담을 수 있지만, 변경 가능성(mutability)에서 성격이 완전히 갈립니다. 실무에서는 이 차이를 명확히 이해해야 버그를 줄이고, 함수 설계와 데이터 모델링도 안정적으로 할 수 있습니다.
핵심 개념
리스트(list)와 튜플(tuple)의 공통점은 다음과 같습니다.
- 여러 값을 순서대로 저장한다.
- 인덱싱, 슬라이싱이 가능하다.
- 반복문(
for)으로 쉽게 순회할 수 있다.
하지만 가장 큰 차이는 수정 가능 여부입니다.
- 리스트: 생성 후 요소 추가/삭제/변경 가능
- 튜플: 생성 후 요소 변경 불가(immutable)
>>> nums = [10, 20, 30]
>>> nums[1] = 99
>>> nums
[10, 99, 30]
>>> point = (3, 7)
>>> point[0] = 10
Traceback (most recent call last):
...
TypeError: 'tuple' object does not support item assignment
이 특성 차이 때문에, “변경될 데이터인가?”를 먼저 묻고 자료구조를 선택하는 습관이 중요합니다.
기본 사용
1) 리스트 생성/수정/확장
>>> tasks = ["백업", "로그정리", "헬스체크"]
>>> tasks.append("리포트생성")
>>> tasks
['백업', '로그정리', '헬스체크', '리포트생성']
>>> tasks.insert(1, "보안점검")
>>> tasks
['백업', '보안점검', '로그정리', '헬스체크', '리포트생성']
>>> done = tasks.pop(0)
>>> done
'백업'
>>> tasks
['보안점검', '로그정리', '헬스체크', '리포트생성']
리스트는 작업 큐, 주문 목록, 수집 데이터 버퍼처럼 “계속 변하는 데이터”에 잘 맞습니다.
2) 튜플로 고정 구조 표현
>>> server = ("api-01", "10.0.0.12", 443)
>>> name, ip, port = server
>>> print(name, ip, port)
api-01 10.0.0.12 443
튜플은 좌표 (x, y), DB 레코드의 일부 스냅샷, 설정값 묶음처럼 의미가 고정된 묶음을 표현할 때 좋습니다.
3) 패킹/언패킹으로 코드 간결화
>>> a, b = 5, 9
>>> a, b = b, a
>>> a, b
(9, 5)
>>> user = ("kim", 29, "premium")
>>> user_id, age, grade = user
>>> user_id
'kim'
임시 변수 없이 값 교환이 가능하고, 함수 반환값 처리도 깔끔해집니다.
4) 실무형 예제: 일별 매출 집계
>>> sales = [120000, 98000, 143000, 87000, 156000]
>>> total = sum(sales)
>>> avg = total / len(sales)
>>> max_day = sales.index(max(sales)) + 1
>>> print(f"총매출: {total:,}원")
>>> print(f"평균매출: {avg:,.0f}원")
>>> print(f"최고 매출일: {max_day}일차")
총매출: 604,000원
평균매출: 120,800원
최고 매출일: 5일차
집계 대상이 계속 추가/수정되는 상황에서는 리스트가 자연스럽고, 결과를 요약한 고정 레코드는 튜플로 반환하면 의도를 분리하기 좋습니다.
자주 하는 실수
실수 1) 리스트 복사 착각(얕은 복사 이슈)
>>> a = [1, 2, 3]
>>> b = a
>>> b.append(4)
>>> a
[1, 2, 3, 4]
b = a는 복사가 아니라 같은 객체를 가리키는 참조 대입입니다. 독립된 사본이 필요하면 a.copy() 또는 a[:]를 사용하세요.
실수 2) 요소 1개짜리 튜플 문법 누락
>>> one = (10)
>>> type(one)
<class 'int'>
>>> one_tuple = (10,)
>>> type(one_tuple)
<class 'tuple'>
튜플 한 개 원소는 반드시 쉼표가 필요합니다.
실수 3) 변경해야 할 데이터를 튜플로 설계
초기에 “안 바뀔 것 같다”는 이유로 튜플을 선택했다가, 요구사항 변경으로 값 업데이트가 필요해지면 구조 변경 비용이 커집니다. 변경 가능성이 조금이라도 있으면 리스트로 시작하고, 안정화된 뒤 튜플로 고정하는 편이 실무적으로 안전합니다.
실수 4) 리스트 메서드 반환값 오해
>>> nums = [3, 1, 2]
>>> result = nums.sort()
>>> result
>>> print(result)
None
>>> nums
[1, 2, 3]
list.sort()는 리스트 자체를 정렬하고 None을 반환합니다. 새 정렬 결과가 필요하면 sorted(nums)를 사용하세요.
오늘의 결론
리스트와 튜플의 선택 기준은 문법이 아니라 데이터의 생명주기입니다.
- 값이 바뀔 가능성이 있으면 리스트를 사용한다.
- 의미적으로 고정된 레코드라면 튜플을 사용한다.
- 리스트 참조/복사 차이를 이해해야 예기치 않은 데이터 오염을 막는다.
- 언패킹을 적극 활용하면 코드 가독성과 유지보수성이 함께 좋아진다.
이 원칙만 지켜도 이후에 배울 함수 인자 설계, 딕셔너리 조합, 파일 파싱 코드가 훨씬 안정적으로 작성됩니다.
연습문제
- 리스트
scores = [72, 88, 95, 64, 83]에서 80점 이상 점수만 새로운 리스트로 만들어 출력해보세요. - 튜플
server = ("db-01", "192.168.0.10", 5432)를 언패킹해 각각 변수에 담고, f-string으로 한 줄 요약을 출력해보세요. - 리스트
items = ["A", "B", "C"]를 복사해items2를 만든 뒤items2에만"D"를 추가했을 때, 원본items가 바뀌지 않도록 코드를 작성해보세요.
이전 강의 정답 (05강 연습문제)
- 1부터 10까지 출력하되 7 건너뛰기 (
continue)
>>> n = 1
>>> while n <= 10:
... if n == 7:
... n += 1
... continue
... print(n)
... n += 1
...
1
2
3
4
5
6
8
9
10
- 비밀번호 최대 3회 시도, 성공 시 즉시 종료
>>> correct = "python100"
>>> tries = 0
>>> success = False
>>> while tries < 3:
... pw = input("비밀번호: ").strip()
... tries += 1
... if pw == correct:
... print("성공")
... success = True
... break
...
비밀번호: 1234
비밀번호: qwer
비밀번호: python100
성공
>>> if not success:
... print("실패")
...
temps에서 25도 이상만 출력
>>> temps = [18, 21, 19, 25, 30, 22]
>>> i = 0
>>> while i < len(temps):
... if temps[i] >= 25:
... print(temps[i])
... i += 1
...
25
30
실습 환경/재현 정보
- 실행 환경:
condaenvpython100(Python 3.11.14)