리스트는 여러 개의 데이터를 하나의 변수에 저장하고 관리할 수 있는 자료구조입니다.
파이썬은 개발자가 편리하게 사용할 수 있도록 다양한 자료구조를 제공하며, 그 중에서도 리스트가 가장 많이 사용됩니다.
일상 생활에서 사용하는 목록과 비슷한 개념으로, 프로그래밍에서 데이터를 효율적으로 처리할 수 있게 해줍니다.
리스트 기본 개념 📋
리스트란?
리스트는 대괄호([])를 사용하여 감싸고 그 안에 저장할 데이터를 쉼표로 구분하여 만듭니다.
파이썬의 리스트는 다른 프로그래밍 언어와 달리 다양한 자료형을 혼합하여 저장할 수 있습니다.
# 기본 리스트 예제
num = 7 # 단일 변수
nums = [0, 1, 2, 3] # 숫자 리스트
# 다양한 자료형 리스트
numbers = [1, 2, 3, 4, 5] # 숫자 리스트
letters = ['a', 'b', 'c', 'd'] # 문자 리스트
booleans = [True, False, True] # 논리값 리스트
names = ['김철수', '이영희', '박민수'] # 문자열 리스트
# 혼합 자료형 리스트 (파이썬만의 특징!)
mixed = [1, 'hello', True, 3.14, 'world']
💡 팁: 파이썬 리스트는 다양한 자료형을 자유롭게 혼합하여 저장할 수 있어 매우 유연합니다! 🎯
1. 리스트 요소와 인덱싱 🔢
리스트 요소
리스트에 들어가는 항목을 요소(element) 또는 엘리먼트라고 부릅니다.
실제 프로그래밍에서는 리스트의 각 요소를 하나씩 다루는 경우가 많습니다.
인덱스 개념
리스트의 특정 요소에 접근하기 위해서는 위치를 사용합니다.
이 위치를 파악하기 위해 사용하는 번호를 인덱스라고 부르며, 0부터 시작합니다.
리스트의 각 요소는 고유한 번호를 가집니다. 이를 인덱스라고 합니다. 파이썬에서는 숫자를 0부터 세기 때문에 인덱스는 항상 0부터 시작합니다.
요소 | 오애순 | 양관식 | 부상길 | 염병철 |
---|---|---|---|---|
양수 인덱스 | 0 | 1 | 2 | 3 |
음수 인덱스 | -4 | -3 | -2 | -1 |
우리는 이 인덱스 값을 사용하여 리스트에서 특정 요소를 추출할 수 있습니다.
# 인덱스 사용 예제
names = ['오애오', '양관식', '부상길', '염병철']
# 양수 인덱스 (0부터 시작)
first_name = names[0] # '방탄소년단'
second_name = names[1] # '아이유'
third_name = names[2] # '트와이스'
last_name = names[3] # '뉴진스'
# 음수 인덱스 (뒤에서부터 시작)
last_name = names[-1] # '뉴진스' (마지막 요소)
second_last = names[-2] # '트와이스'
first_name = names[-4] # '방탄소년단' (첫 번째 요소)
print(f"첫 번째: {first_name}")
print(f"마지막: {last_name}")
⚠️ 주의: 인덱스는 0부터 시작하므로, 리스트의 길이가 n이면 유효한 인덱스는 0부터 n-1까지입니다! 🔍
문자열도 리스트의 한 종류
문자열의 글자 하나하나를 사용하고 싶을 때도 인덱스를 이용할 수 있습니다.
# 문자열 인덱싱
word = "Python"
print(word[0]) # 'P'
print(word[1]) # 'y'
print(word[-1]) # 'n'
print(word[-2]) # 'o'
문제 1 - 리스트 인덱싱 연습 (기초) 🎯
아래 코드의 주석을 참고하여, 리스트 인덱싱을 연습해보세요.
# TODO: 아래 주석을 참고하여 코드를 완성해보세요
fruits = ['사과', '바나나', '오렌지', '포도', '딸기']
# 1. 첫 번째 과일 출력
# first_fruit =
# print("첫 번째 과일:", first_fruit)
# 2. 마지막 과일 출력 (음수 인덱스 사용)
# last_fruit =
# print("마지막 과일:", last_fruit)
# 3. 세 번째 과일 출력
# third_fruit =
# print("세 번째 과일:", third_fruit)
정답 보기
fruits = ['사과', '바나나', '오렌지', '포도', '딸기']
# 1. 첫 번째 과일 출력
first_fruit = fruits[0]
print("첫 번째 과일:", first_fruit)
# 2. 마지막 과일 출력 (음수 인덱스 사용)
last_fruit = fruits[-1]
print("마지막 과일:", last_fruit)
# 3. 세 번째 과일 출력
third_fruit = fruits[2]
print("세 번째 과일:", third_fruit)
# 실행 결과:
# 첫 번째 과일: 사과
# 마지막 과일: 딸기
# 세 번째 과일: 오렌지
2. 리스트 슬라이싱 ✂️
문자열 슬라이싱과 마찬가지로 리스트도 인덱싱을 사용하여 원하는 범위의 요소만 추출하여 새로운 리스트를 만들거나 수정할 수 있습니다.
이 과정을 슬라이싱이라고 합니다.
슬라이싱 기본 구조
리스트[start:stop:step]
- start: 시작 인덱스 (포함)
- stop: 종료 인덱스 (제외)
- step: 간격 (생략 시 1)
슬라이싱 예제
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# 기본 슬라이싱
print(numbers[2:5]) # [2, 3, 4] (2부터 5 미만)
print(numbers[:3]) # [0, 1, 2] (처음부터 3 미만)
print(numbers[7:]) # [7, 8, 9] (7부터 끝까지)
print(numbers[:]) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] (전체)
# 간격을 사용한 슬라이싱
print(numbers[::2]) # [0, 2, 4, 6, 8] (2씩 건너뛰기)
print(numbers[1::2]) # [1, 3, 5, 7, 9] (1부터 2씩 건너뛰기)
print(numbers[::-1]) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] (역순)
# 음수 인덱스 슬라이싱
print(numbers[-3:]) # [7, 8, 9] (뒤에서 3개)
print(numbers[:-2]) # [0, 1, 2, 3, 4, 5, 6, 7] (뒤에서 2개 제외)
💡 팁: 슬라이싱 시 범위를 초과해도 예외가 발생하지 않습니다! 인덱스 접근과 달리 안전합니다! 🛡️
문제 2 - 리스트 슬라이싱 연습 (기초) 🎯
아래 코드의 주석을 참고하여, 슬라이싱을 연습해보세요.
# TODO: 아래 주석을 참고하여 코드를 완성해보세요
colors = ['빨강', '주황', '노랑', '초록', '파랑', '남색', '보라']
# 1. 처음 3개 색상 출력
# first_three =
# print("처음 3개:", first_three)
# 2. 마지막 2개 색상 출력
# last_two =
# print("마지막 2개:", last_two)
# 3. 2번째부터 5번째까지 출력
# middle_colors =
# print("중간 색상들:", middle_colors)
# 4. 역순으로 출력
# reversed_colors =
# print("역순:", reversed_colors)
정답 보기
colors = ['빨강', '주황', '노랑', '초록', '파랑', '남색', '보라']
# 1. 처음 3개 색상 출력
first_three = colors[:3]
print("처음 3개:", first_three)
# 2. 마지막 2개 색상 출력
last_two = colors[-2:]
print("마지막 2개:", last_two)
# 3. 2번째부터 5번째까지 출력
middle_colors = colors[1:5]
print("중간 색상들:", middle_colors)
# 4. 역순으로 출력
reversed_colors = colors[::-1]
print("역순:", reversed_colors)
# 실행 결과:
# 처음 3개: ['빨강', '주황', '노랑']
# 마지막 2개: ['남색', '보라']
# 중간 색상들: ['주황', '노랑', '초록', '파랑']
# 역순: ['보라', '남색', '파랑', '초록', '노랑', '주황', '빨강']
3. 리스트 연산 🔗
파이썬의 리스트는 리스트 간의 다양한 연산도 간단한 연산자로 수행할 수 있도록 지원합니다.
마치 숫자 연산처럼 리스트를 간단한 연산자를 통해 결합하거나 비교할 수 있습니다.
리스트 결합
여러 개의 리스트를 하나의 리스트로 합쳐 새로운 리스트를 만드는 연산입니다.
+ 연산자 사용
# + 연산자로 리스트 결합
list1 = ["A", "B", "C"]
list2 = ["D", "E"]
list3 = ["F", "G", "H"]
# 두 리스트 결합
combined = list1 + list2
print(combined) # ['A', 'B', 'C', 'D', 'E']
# 여러 리스트 결합
all_lists = list1 + list2 + list3
print(all_lists) # ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
extend() 메서드 사용
# extend() 메서드로 리스트 결합
list1 = ["A", "B", "C"]
list2 = ["D", "E"]
print("extend() 전:", list1) # ['A', 'B', 'C']
list1.extend(list2)
print("extend() 후:", list1) # ['A', 'B', 'C', 'D', 'E']
💡 차이점: + 연산자는 새로운 리스트를 생성하지만, extend() 메서드는 기존 리스트를 수정합니다! 🔄
리스트 반복
하나의 리스트를 여러 번 반복하여 결합하고 싶은 경우 사용합니다.
# * 연산자로 리스트 반복
base_list = ["Hello", "World"]
repeated = base_list * 3
print(repeated) # ['Hello', 'World', 'Hello', 'World', 'Hello', 'World']
# + 연산자로 반복 (비효율적)
manual_repeat = base_list + base_list + base_list
print(manual_repeat) # ['Hello', 'World', 'Hello', 'World', 'Hello', 'World']
4. 리스트 메서드 🛠️
파이썬의 리스트는 단순한 연산뿐만 아니라, 개발자가 리스트를 더욱 효율적으로 활용할 수 있도록 다양한 메서드를 제공합니다.
리스트 추가: append(), insert()
append() 메서드
리스트의 마지막에 새로운 요소를 추가합니다.
# append() 메서드 예제
fruits = ['사과', '바나나']
print("추가 전:", fruits) # ['사과', '바나나']
fruits.append('오렌지')
print("추가 후:", fruits) # ['사과', '바나나', '오렌지']
fruits.append('포도')
print("최종:", fruits) # ['사과', '바나나', '오렌지', '포도']
insert() 메서드
원하는 특정 위치에 자유롭게 요소를 삽입할 수 있습니다.
# insert() 메서드 예제
fruits = ['사과', '바나나', '포도']
print("삽입 전:", fruits) # ['사과', '바나나', '포도']
# 1번 인덱스에 '오렌지' 삽입
fruits.insert(1, '오렌지')
print("삽입 후:", fruits) # ['사과', '오렌지', '바나나', '포도']
# 맨 앞에 삽입
fruits.insert(0, '딸기')
print("맨 앞 삽입:", fruits) # ['딸기', '사과', '오렌지', '바나나', '포도']
💡 팁: append()는 마지막에만 추가 가능하지만, insert()는 원하는 위치에 자유롭게 삽입할 수 있습니다! 🎯
문제 3 - 리스트 추가 연습 (중급) 🎯
아래 코드의 주석을 참고하여, append()와 insert()를 사용해보세요.
# TODO: 아래 주석을 참고하여 코드를 완성해보세요
shopping_list = ['우유', '빵']
# 1. append()로 '계란' 추가
# 2. insert()로 '사과'를 맨 앞에 추가
# 3. insert()로 '치즈'를 2번째 위치에 추가
# print("최종 쇼핑 리스트:", shopping_list)
# 예상 결과: ['사과', '우유', '치즈', '빵', '계란']
정답 보기
shopping_list = ['우유', '빵']
# 1. append()로 '계란' 추가
shopping_list.append('계란')
# 2. insert()로 '사과'를 맨 앞에 추가
shopping_list.insert(0, '사과')
# 3. insert()로 '치즈'를 2번째 위치에 추가
shopping_list.insert(2, '치즈')
print("최종 쇼핑 리스트:", shopping_list)
# 실행 결과: ['사과', '우유', '치즈', '빵', '계란']
리스트 삭제: remove(), pop()
리스트 요소를 삭제하는 방법에는 두 가지가 있습니다.
remove() 메서드
특정 값을 가진 요소를 삭제합니다.
# remove() 메서드 예제
fruits = ['사과', '바나나', '오렌지', '바나나']
print("삭제 전:", fruits) # ['사과', '바나나', '오렌지', '바나나']
fruits.remove('바나나')
print("삭제 후:", fruits) # ['사과', '오렌지', '바나나'] (첫 번째 '바나나'만 삭제)
# 존재하지 않는 값 삭제 시도 (에러 발생)
# fruits.remove('포도') # ValueError: list.remove(x): x not in list
⚠️ 주의: 동일한 값이 여러 개 있어도 처음 발견된 하나만 삭제됩니다! 삭제할 값이 없으면 예외가 발생합니다! 🚨
pop() 메서드
특정 위치에 있는 요소를 삭제하고 그 값을 반환합니다.
# pop() 메서드 예제
fruits = ['사과', '바나나', '오렌지', '포도']
print("삭제 전:", fruits) # ['사과', '바나나', '오렌지', '포도']
# 특정 위치 삭제
removed = fruits.pop(1)
print(f"삭제된 요소: {removed}") # 삭제된 요소: 바나나
print("삭제 후:", fruits) # ['사과', '오렌지', '포도']
# 매개변수 없이 사용 (마지막 요소 삭제)
last_item = fruits.pop()
print(f"마지막 요소: {last_item}") # 마지막 요소: 포도
print("최종:", fruits) # ['사과', '오렌지']
💡 차이점: remove()는 값을 기준으로 삭제하고 반환값이 없지만, pop()은 인덱스를 기준으로 삭제하고 삭제된 값을 반환합니다! 🔄
리스트 길이 확인: len()
리스트의 길이를 확인하는 데 사용하는 함수입니다.
# len() 함수 예제
fruits = ['사과', '바나나', '오렌지']
print(f"리스트 길이: {len(fruits)}") # 리스트 길이: 3
# 빈 리스트
empty_list = []
print(f"빈 리스트 길이: {len(empty_list)}") # 빈 리스트 길이: 0
# 리스트 순회와 함께 사용
for i in range(len(fruits)):
print(f"{i+1}번째 과일: {fruits[i]}")
리스트 정렬: sort(), sorted()
데이터를 분석하거나 활용하기 위해서는 정렬된 상태로 유지하는 것이 중요합니다.
sort() 메서드
리스트를 자동으로 정렬하여 원본 리스트를 변경합니다.
# sort() 메서드 예제
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
print("정렬 전:", numbers) # [3, 1, 4, 1, 5, 9, 2, 6]
numbers.sort()
print("오름차순 정렬:", numbers) # [1, 1, 2, 3, 4, 5, 6, 9]
# 내림차순 정렬
numbers.sort(reverse=True)
print("내림차순 정렬:", numbers) # [9, 6, 5, 4, 3, 2, 1, 1]
sorted() 함수
새로운 정렬된 리스트를 반환하며, 원본 리스트는 변경되지 않습니다.
# sorted() 함수 예제
original = [3, 1, 4, 1, 5, 9, 2, 6]
print("원본:", original) # [3, 1, 4, 1, 5, 9, 2, 6]
# 오름차순 정렬
ascending = sorted(original)
print("오름차순:", ascending) # [1, 1, 2, 3, 4, 5, 6, 9]
print("원본 유지:", original) # [3, 1, 4, 1, 5, 9, 2, 6]
# 내림차순 정렬
descending = sorted(original, reverse=True)
print("내림차순:", descending) # [9, 6, 5, 4, 3, 2, 1, 1]
리스트 반전: reverse()
리스트의 요소 순서를 반전시켜 원본 리스트를 변경합니다.
# reverse() 메서드 예제
numbers = [1, 2, 3, 4, 5]
print("반전 전:", numbers) # [1, 2, 3, 4, 5]
numbers.reverse()
print("반전 후:", numbers) # [5, 4, 3, 2, 1]
요소 존재 확인: in 키워드
리스트에 특정 값이 존재하는지 확인하는 데 사용합니다.
# in 키워드 예제
fruits = ['사과', '바나나', '오렌지']
# 요소 존재 확인
print('사과' in fruits) # True
print('포도' in fruits) # False
# not in 사용
print('포도' not in fruits) # True
print('사과' not in fruits) # False
# 조건문과 함께 사용
if '바나나' in fruits:
print("바나나가 있습니다!")
else:
print("바나나가 없습니다.")
리스트를 문자열로 변환: join()
리스트의 요소들을 하나의 문자열로 연결합니다.
# join() 메서드 예제
words = ['Hello', 'World', 'Python']
sentence = ' '.join(words)
print(sentence) # Hello World Python
# 다른 구분자 사용
fruits = ['사과', '바나나', '오렌지']
fruit_string = ', '.join(fruits)
print(fruit_string) # 사과, 바나나, 오렌지
# 빈 문자열로 연결
letters = ['P', 'y', 't', 'h', 'o', 'n']
word = ''.join(letters)
print(word) # Python
5. 실전 예제 🚀
예제 1: 학생 성적 관리
# 학생 성적 리스트
scores = [85, 92, 78, 96, 88, 73, 91, 87]
# 성적 통계 계산
total = sum(scores)
average = total / len(scores)
highest = max(scores)
lowest = min(scores)
print(f"총점: {total}")
print(f"평균: {average:.2f}")
print(f"최고점: {highest}")
print(f"최저점: {lowest}")
# 90점 이상 학생 수
high_scores = [score for score in scores if score >= 90]
print(f"90점 이상 학생 수: {len(high_scores)}")
예제 2: 쇼핑 리스트 관리
# 쇼핑 리스트 관리 시스템
shopping_list = []
def add_item(item):
shopping_list.append(item)
print(f"'{item}'이(가) 추가되었습니다.")
def remove_item(item):
if item in shopping_list:
shopping_list.remove(item)
print(f"'{item}'이(가) 삭제되었습니다.")
else:
print(f"'{item}'이(가) 리스트에 없습니다.")
def show_list():
if shopping_list:
print("현재 쇼핑 리스트:")
for i, item in enumerate(shopping_list, 1):
print(f"{i}. {item}")
else:
print("쇼핑 리스트가 비어있습니다.")
# 사용 예제
add_item("우유")
add_item("빵")
add_item("계란")
show_list()
remove_item("빵")
show_list()
예제 3: 숫자 게임
import random
# 1부터 100까지의 랜덤한 숫자 10개 생성
numbers = [random.randint(1, 100) for _ in range(10)]
print(f"생성된 숫자들: {numbers}")
# 정렬
numbers.sort()
print(f"정렬된 숫자들: {numbers}")
# 짝수만 필터링
even_numbers = [num for num in numbers if num % 2 == 0]
print(f"짝수들: {even_numbers}")
# 평균 계산
average = sum(numbers) / len(numbers)
print(f"평균: {average:.2f}")
6. 주의사항 및 팁 ⚠️
리스트 사용 시 주의사항
- 인덱스 범위: 인덱스는 0부터 시작하며, 범위를 벗어나면 IndexError가 발생합니다.
- 원본 변경: 대부분의 메서드가 원본 리스트를 변경하므로 주의해야 합니다.
- 메모리 효율성: 큰 리스트의 경우 슬라이싱보다 인덱싱이 더 효율적입니다.
성능 최적화 팁
# 비효율적인 코드
result = []
for i in range(len(numbers)):
result.append(numbers[i] * 2)
# 효율적인 코드 (리스트 컴프리헨션)
result = [num * 2 for num in numbers]
# 또는 map() 함수 사용
result = list(map(lambda x: x * 2, numbers))
디버깅 팁
# 리스트 디버깅을 위한 print문 활용
fruits = ['사과', '바나나', '오렌지']
for i, fruit in enumerate(fruits):
print(f"인덱스 {i}: {fruit}")
# 리스트 상태 확인
print(f"리스트 길이: {len(fruits)}")
print(f"리스트 내용: {fruits}")
💡 팁: 리스트를 사용할 때는 메모리 효율성과 가독성을 고려하여 적절한 메서드를 선택하세요! 복잡한 작업은 작은 단위로 나누어 구현하는 것이 좋습니다! 🎯
7. 연습 문제 🎯
문제 1: 리스트 기본 조작 (기초)
다음 요구사항을 만족하는 프로그램을 작성하세요:
- 빈 리스트를 만들고 5개의 과일 이름을 추가
- 2번째 위치에 ‘딸기’를 삽입
- 마지막 요소를 삭제하고 삭제된 요소 출력
- 리스트를 정렬하여 출력
문제 2: 성적 분석 (중급)
학생들의 성적 리스트가 주어졌을 때:
- 평균 점수 계산
- 90점 이상인 학생 수 계산
- 최고점과 최저점의 차이 계산
- 성적을 내림차순으로 정렬하여 출력
문제 3: 리스트 변환 (고급)
문자열 리스트를 다음과 같이 변환하는 프로그램을 작성하세요:
- 모든 문자열을 대문자로 변환
- 문자열 길이가 5 이상인 것만 필터링
- 필터링된 문자열들을 하나의 문자열로 연결 (공백으로 구분)
정답 보기
# 문제 1: 리스트 기본 조작
fruits = []
fruits.extend(['사과', '바나나', '오렌지', '포도', '수박'])
fruits.insert(1, '딸기')
removed = fruits.pop()
print(f"삭제된 요소: {removed}")
fruits.sort()
print(f"정렬된 리스트: {fruits}")
# 문제 2: 성적 분석
scores = [85, 92, 78, 96, 88, 73, 91, 87]
average = sum(scores) / len(scores)
high_scores = len([s for s in scores if s >= 90])
score_range = max(scores) - min(scores)
sorted_scores = sorted(scores, reverse=True)
print(f"평균: {average:.2f}")
print(f"90점 이상: {high_scores}명")
print(f"점수 범위: {score_range}")
print(f"내림차순: {sorted_scores}")
# 문제 3: 리스트 변환
words = ['hello', 'world', 'python', 'programming', 'code']
upper_words = [word.upper() for word in words]
filtered_words = [word for word in upper_words if len(word) >= 5]
result = ' '.join(filtered_words)
print(f"결과: {result}")
리스트는 파이썬에서 가장 중요한 자료구조 중 하나입니다. 다양한 메서드와 연산을 활용하여 데이터를 효율적으로 관리하고 처리할 수 있습니다. 실습을 통해 리스트의 다양한 기능을 익혀보세요! 🚀