4. 리스트와 튜플

리스트와 튜플은 파이썬에서 데이터를 저장하고 관리하는 데 사용되는 가장 기본적인 자료구조입니다. 두 데이터 타입 모두 여러 값을 하나의 변수에 저장할 수 있지만, 리스트는 변경 가능한 (mutable) 반면, 튜플은 변경 불가능한(immutable) 특성을 가지고 있습니다. 프로그래밍을 처음 배울때는 ‘무조건 변경 가능한 데이터 타입이 더 좋은게 아닌가, 튜플이 왜 필요하지?’ 라고 생각할 수 있습니다. 이번 챕터에서 리스트와 튜플의 사용법을 익히는 동시에 어떨 때 리스트 대신 튜플을 사용하는지 익혀봅시다.

4.1 리스트

리스트는 여러 개의 값을 순서대로 저장할 수 있는 자료구조입니다. 리스트는 대괄호 []로 정의되며, 각 항목은 콤마로 구분됩니다. 리스트는 값을 추가, 삭제, 수정할 수 있습니다.

# 리스트 생성 예제
fruits = ["사과", "바나나", "체리"]
print(fruits)

출력 결과:

['사과', '바나나', '체리']

4.1.1 리스트의 인덱스와 주요 기능

리스트의 각 항목은 인덱스를 통해 접근할 수 있습니다. 인덱스란 리스트 내의 각 항목에 부여된 고유한 번호라고 생각하면 됩니다. 예를 들어, 첫 번째 항목은 인덱스 0, 두 번째 항목은 인덱스 1과 같이 번호가 매겨집니다. 음수를 사용하면 리스트의 끝에서부터 역순으로 접근할 수 있습니다. 예를 들어, 인덱스 -1은 마지막 항목, 그리고 인덱스 -2은 마지막에서 두번째 항목을 의미합니다. 여기서 코딩을 처음 접하는 사람들이 생소하게 생각하는 것은 첫번째 자리에 있는 항목의 인덱스가 1이 아니라 0이라는 겁니다 (이걸 “zero-based indexing” 이라고 합니다). 중요한 개념이니까 아래의 예시들을 보면서 반드시 숙지해주세요.

인덱스 예시

# 인덱스로 항목 접근하기
fruits = ["사과", "바나나", "체리"]
print(fruits[0])  # 첫번째 항목인 '사과' 가 출력
print(fruits[1])  # 두번째 항목인 '바나나' 가 출력
print(fruits[-1])  # 마지막 항목인 '체리' 가 출력

출력 결과:

사과
바나나
체리

이제 리스트의 주요 기능들을 살펴보겠습니다. 리스트에는 다양한 기능을 제공하는 함수들이 있습니다. 함수에 대한 개념과 사용법은 나중에 함수 챕터에서 좀 더 자세히 다룰 예정이니까 밑의 코드가 확실하게 이해가 안되더라도 일단은 넘어갔다가 함수에 대한 개념을 익힌 후에 다시 돌아와도 됩니다.

  • 항목 추가하기 (append())

    리스트의 끝에 항목을 추가할 때 append() 함수를 사용합니다.

    fruits = ["사과", "바나나", "체리"]
    fruits.append("포도")
    print(fruits)
    

    출력 결과:

    ['사과', '바나나', '체리', '포도']
    
  • 항목 삽입하기 (insert())

    특정 위치에 항목을 삽입할 때 insert() 함수를 사용합니다.

    fruits.insert(1, "오렌지")
    print(fruits)
    

    출력 결과:

    ['사과', '오렌지', '바나나', '체리', '포도']
    
  • 항목 제거하기 (remove())

    리스트에서 특정 값을 제거할 때 remove() 함수를 사용합니다.

    fruits.remove("바나나")
    print(fruits)
    

    출력 결과:

    ['사과', '오렌지', '체리', '포도']
    
  • 인덱스로 항목 제거하기 (pop())

    pop() 함수는 지정된 인덱스의 항목을 제거하고 반환합니다. 인덱스를 지정하지 않으면 마지막 항목이 제거됩니다.

    fruit = fruits.pop(2)
    print(fruit)  # '체리'
    print(fruits)
    

    출력 결과:

    ['사과', '오렌지', '포도']
    
  • 항목 찾기 (index())

    리스트에서 특정 항목의 인덱스를 찾을 때 index() 함수를 사용합니다.

    index = fruits.index("오렌지")
    print(index)
    

    출력 결과:

    1
    

4.1.2 리스트 슬라이싱

리스트의 특정 부분을 추출할 때 슬라이싱을 사용할 수 있습니다. 슬라이싱은 [start_index:stop_index:step] 형식으로 사용됩니다. 여기서 start_index는 슬라이싱을 시작할 위치, stop_index는 슬라이싱을 멈출 위치이며, step은 몇 칸씩 건너뛰며 추출할지를 결정합니다. 중요한 점은 stop_index에 해당하는 값은 포함되지 않고 그 바로 직전 값까지만 포함된다는 것입니다. 수학적으로 표현하자면 [start_index, stop_index)와 같습니다. 아래의 예시를 봅시다.

numbers = [0, 1, 2, 3, 4, 5]
print(numbers[1:4])  # [1, 2, 3]
print(numbers[:3])   # [0, 1, 2]
print(numbers[::2])  # [0, 2, 4]

이해를 돕기 위해 더 많은 예시를 살펴보겠습니다.

numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 인덱스 2부터 5까지 슬라이싱 (5는 포함되지 않음)
print(numbers[2:5])  # [2, 3, 4]

# 인덱스 6부터 끝까지 슬라이싱
print(numbers[6:])  # [6, 7, 8, 9]

# 처음부터 인덱스 4까지 슬라이싱 (4는 포함되지 않음)
print(numbers[:4])  # [0, 1, 2, 3]

# 전체 리스트를 2칸씩 건너뛰며 슬라이싱
print(numbers[::2])  # [0, 2, 4, 6, 8]

# 리스트를 역순으로 슬라이싱
print(numbers[::-1])  # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

출력 결과:

[2, 3, 4]
[6, 7, 8, 9]
[0, 1, 2, 3]
[0, 2, 4, 6, 8]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

이처럼 슬라이싱을 사용하면 리스트의 특정 부분을 손쉽게 추출할 수 있습니다. 특히 리스트를 역순으로 정렬하거나 일정한 간격으로 값을 추출할 때 매우 유용합니다.

4.2 튜플

튜플은 리스트와 유사하지만, 생성된 후에는 값을 변경할 수 없습니다. 튜플은 소괄호 ()로 정의되며, 각 항목은 콤마로 구분됩니다. 불변성이 요구되는 데이터를 저장할 때 유용합니다.

# 튜플 생성 예제
colors = ("빨강", "초록", "파랑")
print(colors)

출력 결과:

('빨강', '초록', '파랑')

4.2.1 튜플의 인덱스와 주요 기능

튜플의 각 항목은 리스트와 동일하게 인덱스를 통해 접근할 수 있습니다. 인덱스는 0부터 시작하며, 음수를 사용하여 뒤에서부터 접근할 수도 있습니다.

# 인덱스로 항목 접근하기
colors = ("빨강", "초록", "파랑")
print(colors[0])  # 첫번째 항목인 '빨강' 가 출력
print(colors[-1])  # 마지막 항목인 '파랑' 가 출력

출력 결과:

빨강
파랑

튜플의 주요 기능은 리스트와 유사하지만, 튜플은 불변이기 때문에 값을 변경하거나 추가, 삭제할 수 없습니다. 하지만 일부 기능들은 여전히 유용하게 사용할 수 있습니다.

  • 항목 찾기 (index())

    튜플에서 특정 항목의 인덱스를 찾을 때 index() 함수를 사용합니다.

    index = colors.index("초록")
    print(index)
    

    출력 결과:

    1
    
  • 항목 개수 세기 (count())

    튜플에서 특정 값이 몇 번 나타나는지를 셀 때 count() 함수를 사용합니다.

    numbers = (1, 2, 3, 1, 1, 4)
    count = numbers.count(1)
    print(count)
    

    출력 결과:

    3
    

4.2.2 튜플 사용 예시

튜플은 변경이 필요 없는 데이터를 저장할 때 주로 사용됩니다. 예를 들어, 좌표 값이나 데이터베이스의 레코드와 같은 데이터에 사용됩니다.

# 좌표 값 저장 예제
point = (10, 20)
print(f"x: {point[0]}, y: {point[1]}")

출력 결과:

x: 10, y: 20

4.3 리스트와 튜플의 차이점

특징 리스트 (list) 튜플 (tuple)
가변성 변경 가능 (mutable) 변경 불가능 (immutable)
선언 방법 대괄호 [] 소괄호 ()
사용 예시 데이터 추가/삭제가 필요한 경우 불변 데이터 (좌표, 설정 값 등)
성능 데이터 변경이 빈번한 경우 적합 데이터 변경이 적고 읽기만 하는 경우 적합

4.4 예제: 학생 정보 관리하기

리스트와 튜플을 사용하여 학생 정보를 관리해 보겠습니다.

  • 학생의 이름, 나이, 학년 정보를 저장하는 튜플을 사용하고, 이러한 학생 정보를 리스트에 저장합니다.
# 학생 정보 저장 예제
students = [
    ("철수", 15, 1),
    ("영희", 16, 2),
    ("민수", 14, 1)
]

# 모든 학생 정보 출력
for student in students:
    name, age, grade = student
    print(f"이름: {name}, 나이: {age}, 학년: {grade}")

출력 결과:

이름: 철수, 나이: 15, 학년: 1
이름: 영희, 나이: 16, 학년: 2
이름: 민수, 나이: 14, 학년: 1

위에서 사용한 for .. in 문법은 나중에 반복문 챕터에서 더 자세하게 다룰 예정입니다.

4.5 요약

  • 리스트와 튜플은 여러 값을 저장할 수 있는 자료구조입니다.
  • 리스트는 가변적이며, 값을 추가, 삭제, 수정할 수 있습니다.
  • 튜플은 불변적이며, 생성 후에는 값을 변경할 수 없습니다.
  • 리스트는 데이터가 자주 변경될 때, 튜플은 변경되지 않는 데이터를 저장할 때 사용합니다.

이제 리스트와 튜플을 사용하여 데이터를 저장하고 관리할 수 있게 되었습니다. 다음 장에서는 딕셔너리와 집합에 대해 배워보겠습니다.