
Python 리스트 기본 개념
Python에서 리스트(List)는 여러 개의 항목을 순서대로 저장할 수 있는 가변(mutable) 데이터 구조다. 리스트는 대괄호([])로 생성하며, 서로 다른 데이터 타입의 요소들을 동시에 저장할 수 있다. 리스트는 Python에서 가장 유연하고 강력한 데이터 구조 중 하나로, 데이터 수집, 정렬, 필터링 등 다양한 데이터 처리 작업에서 핵심적인 역할을 담당한다.
리스트는 인덱스를 통해 각 요소에 접근할 수 있으며, 인덱스는 0부터 시작한다. 음수 인덱스를 사용하여 뒤에서부터 요소에 접근하는 것도 가능하다. 이러한 특성들로 인해 리스트는 프로그래밍에서 가장 빈번하게 사용되는 컬렉션 타입이다.
리스트의 주요 특성
Python 리스트는 세 가지 핵심 특성을 가지고 있다.
특성 | 의미 | 설명 | 예시 |
---|---|---|---|
순서 유지 (Ordered) | 정의된 순서가 유지된다 | 항목이 추가된 순서가 보존되며 변경되지 않는다 | [“a”, “b”, “c”]는 항상 그 순서를 유지한다 |
변경 가능 (Changeable) | 생성 후에도 수정할 수 있다 | 항목을 변경, 추가, 제거할 수 있다 | items[1] = “x”로 값 변경 가능 |
중복 허용 (Allow Duplicates) | 동일한 값을 여러 번 포함할 수 있다 | 같은 값이 여러 위치에 존재해도 된다 | [“a”, “a”, “b”]와 같은 형태 가능 |
리스트 생성과 기본 조작
리스트는 대괄호 안에 쉼표로 구분된 값들을 나열하여 생성한다. 빈 리스트부터 다양한 데이터 타입을 포함한 리스트까지 자유롭게 만들 수 있다.
다양한 리스트 생성 방법
fruits = ["apple", "banana", "cherry"]
numbers = [1, 5, 7, 9, 3]
mixed_list = ["hello", 42, True, 3.14]
empty_list = []
built_from_tuple = list(("apple", "banana", "cherry"))
print(f"과일 리스트: {fruits}")
print(f"숫자 리스트: {numbers}")
print(f"혼합 리스트: {mixed_list}")
print(f"빈 리스트: {empty_list}")
print(f"튜플에서 생성: {built_from_tuple}")
리스트 길이와 타입 확인
fruits = ["apple", "banana", "cherry", "banana"]
print(f"리스트 길이: {len(fruits)}")
print(f"리스트 타입: {type(fruits)}")
print(f"리스트 인스턴스 확인: {isinstance(fruits, list)}")
print(f"'banana' 포함 여부: {'banana' in fruits}")
print(f"'orange' 미포함 여부: {'orange' not in fruits}")
위 코드는 4, <class ‘list’>, True, True, True를 각각 출력한다.
리스트 요소 접근
리스트의 각 요소는 인덱스를 통해 접근할 수 있다. Python은 양수와 음수 인덱스를 모두 지원한다.
인덱싱
fruits = ["apple", "banana", "cherry", "date", "elderberry"]
print(f"첫 번째 과일: {fruits[0]}")
print(f"두 번째 과일: {fruits[1]}")
print(f"마지막 과일: {fruits[-1]}")
print(f"뒤에서 두 번째: {fruits[-2]}")
위 코드는 “apple”, “banana”, “elderberry”, “date”를 각각 출력한다.
슬라이싱
슬라이싱을 사용하여 리스트의 일부분을 추출할 수 있다. 시작 인덱스는 포함되고 끝 인덱스는 포함되지 않는다.
fruits = ["apple", "banana", "cherry", "date", "elderberry"]
print(f"인덱스 1부터 3까지: {fruits[1:4]}")
print(f"처음부터 인덱스 2까지: {fruits[:3]}")
print(f"인덱스 2부터 끝까지: {fruits[2:]}")
print(f"뒤에서 3개부터 1개까지: {fruits[-3:-1]}")
print(f"전체 리스트 복사: {fruits[:]}")
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(f"짝수 인덱스 요소들: {numbers[::2]}")
print(f"역순으로: {numbers[::-1]}")
위 코드는 [‘banana’, ‘cherry’, ‘date’], [‘apple’, ‘banana’, ‘cherry’], [‘cherry’, ‘date’, ‘elderberry’], [‘cherry’, ‘date’], 전체 리스트, [0, 2, 4, 6, 8], [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]을 각각 출력한다.
리스트 요소 변경
리스트는 가변 객체이므로 생성 후에도 요소를 자유롭게 변경할 수 있다.
단일 및 범위 요소 변경
fruits = ["apple", "banana", "cherry", "date"]
print(f"변경 전: {fruits}")
fruits[1] = "blueberry"
print(f"단일 변경 후: {fruits}")
fruits[1:3] = ["mango", "pineapple"]
print(f"범위 변경 후: {fruits}")
fruits[1:4] = ["orange"]
print(f"길이 변경: {fruits}")
위 코드는 원본 리스트에서 시작하여 각 변경 단계를 보여준다.
리스트 요소 추가
리스트에 새로운 요소를 추가하는 여러 가지 방법이 있다.
추가 메서드들
fruits = ["apple", "banana"]
print(f"초기 리스트: {fruits}")
fruits.append("cherry")
print(f"append 후: {fruits}")
fruits.insert(1, "blueberry")
print(f"insert 후: {fruits}")
tropical = ["mango", "pineapple"]
fruits.extend(tropical)
print(f"extend 후: {fruits}")
fruits += ["papaya", "kiwi"]
print(f"+ 연산자 후: {fruits}")
위 코드는 각 단계별로 리스트가 확장되는 과정을 보여준다.
리스트 요소 제거
리스트에서 요소를 제거하는 다양한 방법을 제공한다.
제거 메서드들
fruits = ["apple", "banana", "cherry", "banana", "date"]
print(f"제거 전: {fruits}")
fruits.remove("banana")
print(f"remove 후 (첫 번째 banana만 제거): {fruits}")
removed_item = fruits.pop(1)
print(f"pop(1) 후: {fruits}")
print(f"제거된 항목: {removed_item}")
last_item = fruits.pop()
print(f"pop() 후: {fruits}")
print(f"마지막 항목: {last_item}")
del fruits[0]
print(f"del fruits[0] 후: {fruits}")
fruits_copy = fruits.copy()
fruits.clear()
print(f"clear 후: {fruits}")
print(f"백업 리스트: {fruits_copy}")
리스트 순회
리스트의 모든 요소를 순회하는 다양한 방법이 있다.
다양한 반복 방법
fruits = ["apple", "banana", "cherry"]
print("기본 for 반복문:")
for fruit in fruits:
print(f"- {fruit}")
print("\n인덱스와 함께 순회:")
for i, fruit in enumerate(fruits):
print(f"{i}: {fruit}")
print("\nrange를 사용한 인덱스 접근:")
for i in range(len(fruits)):
print(f"{i}: {fruits[i]}")
print("\nwhile 반복문:")
i = 0
while i < len(fruits):
print(f"- {fruits[i]}")
i += 1[/code]
리스트 컴프리헨션
리스트 컴프리헨션은 기존 리스트를 기반으로 새로운 리스트를 생성하는 간결하고 강력한 방법이다.
기본 및 조건부 컴프리헨션
[code lang="python"]numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
squares = [x**2 for x in numbers]
print(f"제곱수: {squares}")
even_numbers = [x for x in numbers if x % 2 == 0]
print(f"짝수: {even_numbers}")
fruits = ["apple", "banana", "cherry", "apricot"]
a_fruits = [fruit.upper() for fruit in fruits if fruit.startswith('a')]
print(f"a로 시작하는 과일(대문자): {a_fruits}")
result = ["짝수" if x % 2 == 0 else "홀수" for x in numbers[:5]]
print(f"짝수/홀수 판별: {result}")
리스트 정렬과 순서 변경
리스트의 요소를 정렬하거나 순서를 변경하는 메서드들이 있다.
정렬 메서드
numbers = [64, 34, 25, 12, 22, 11, 90]
fruits = ["banana", "Apple", "cherry", "Date"]
numbers_copy = numbers.copy()
numbers_copy.sort()
print(f"오름차순 정렬: {numbers_copy}")
numbers_copy = numbers.copy()
numbers_copy.sort(reverse=True)
print(f"내림차순 정렬: {numbers_copy}")
fruits_copy = fruits.copy()
fruits_copy.sort(key=str.lower)
print(f"대소문자 무시 정렬: {fruits_copy}")
numbers_copy = numbers.copy()
numbers_copy.reverse()
print(f"순서 뒤집기: {numbers_copy}")
sorted_numbers = sorted(numbers)
print(f"원본 유지 정렬: {sorted_numbers}")
print(f"원본 리스트: {numbers}")
리스트 복사와 결합
리스트를 복사하거나 여러 리스트를 결합하는 방법들이 있다.
복사 및 결합 방법
original = ["apple", "banana", "cherry"]
copy1 = original.copy()
copy2 = list(original)
copy3 = original[:]
print(f"원본: {original}")
print(f"copy() 방법: {copy1}")
print(f"list() 방법: {copy2}")
print(f"슬라이싱 방법: {copy3}")
list1 = ["a", "b", "c"]
list2 = [1, 2, 3]
combined1 = list1 + list2
print(f"+ 연산자로 결합: {combined1}")
list1_copy = list1.copy()
list1_copy.extend(list2)
print(f"extend로 결합: {list1_copy}")
print(f"원본 list1: {list1}")
리스트 메서드 종합 표
메서드 | 기능 | 반환값 | 원본 변경 | 예시 |
---|---|---|---|---|
append(item) | 리스트 끝에 요소 추가 | None | O | list.append("new") |
insert(index, item) | 지정 위치에 요소 삽입 | None | O | list.insert(1, "new") |
extend(iterable) | 반복 가능한 객체의 모든 요소 추가 | None | O | list.extend([1, 2, 3]) |
remove(item) | 첫 번째 일치 요소 제거 | None | O | list.remove("apple") |
pop(index) | 지정 인덱스 요소 제거 및 반환 | 제거된 요소 | O | item = list.pop(0) |
clear() | 모든 요소 제거 | None | O | list.clear() |
index(item) | 요소의 첫 번째 인덱스 반환 | int | X | idx = list.index("apple") |
count(item) | 요소의 개수 반환 | int | X | cnt = list.count("apple") |
sort() | 리스트를 정렬 | None | O | list.sort(reverse=True) |
reverse() | 리스트 순서 뒤집기 | None | O | list.reverse() |
copy() | 리스트의 얕은 복사본 생성 | 새로운 리스트 | X | new_list = list.copy() |
실무 활용 예제
리스트를 활용한 실제 프로그래밍 패턴들을 살펴보자.
데이터 필터링과 변환
students = [
{"name": "Alice", "score": 85, "grade": "B"},
{"name": "Bob", "score": 92, "grade": "A"},
{"name": "Charlie", "score": 78, "grade": "C"},
{"name": "Diana", "score": 96, "grade": "A"}
]
high_achievers = [s for s in students if s["score"] >= 90]
print(f"고득점자: {[s['name'] for s in high_achievers]}")
score_summary = [(s["name"], s["score"]) for s in students]
print(f"점수 요약: {score_summary}")
a_grade_count = len([s for s in students if s["grade"] == "A"])
print(f"A등급 학생 수: {a_grade_count}")
리스트 집계와 통계
scores = [85, 92, 78, 96, 73, 88, 91]
total = sum(scores)
average = total / len(scores)
maximum = max(scores)
minimum = min(scores)
print(f"총점: {total}")
print(f"평균: {average:.2f}")
print(f"최고점: {maximum}")
print(f"최저점: {minimum}")
above_average = [score for score in scores if score > average]
print(f"평균 이상 점수: {above_average}")
sorted_scores = sorted(scores, reverse=True)
print(f"내림차순 정렬: {sorted_scores}")
중첩 리스트 처리
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
print("행렬 출력:")
for i, row in enumerate(matrix):
print(f"행 {i}: {row}")
flattened = [item for row in matrix for item in row]
print(f"평탄화: {flattened}")
transposed = [[row[i] for row in matrix] for i in range(len(matrix[0]))]
print(f"전치 행렬: {transposed}")
diagonal = [matrix[i][i] for i in range(len(matrix))]
print(f"대각선 요소: {diagonal}")
💡 리스트 활용 모범 사례:
• 리스트 컴프리헨션을 활용하여 간결하고 효율적인 코드를 작성한다
• 큰 리스트에서는 필요한 부분만 슬라이싱하여 메모리를 절약한다
• enumerate()를 사용하여 인덱스와 값을 함께 처리한다
• sort()는 원본을 변경하고 sorted()는 새 리스트를 반환한다는 차이를 이해한다
• 리스트 복사 시 copy() 메서드나 슬라이싱을 사용하여 독립적인 복사본을 만든다
• extend()는 개별 요소를 추가하고 append()는 객체 전체를 하나의 요소로 추가한다
• 성능이 중요한 경우 리스트보다 적절한 자료구조를 고려한다
• in 연산자를 사용하여 요소 존재 여부를 효율적으로 확인한다
Python의 리스트는 데이터 처리의 핵심 도구로서 순서가 있는 데이터 컬렉션을 효율적으로 관리할 수 있게 해준다. 인덱싱, 슬라이싱, 다양한 메서드들을 적절히 활용하면 복잡한 데이터 조작 작업을 간결하고 직관적으로 수행할 수 있으며, 리스트 컴프리헨션과 같은 고급 기능을 통해 더욱 파이썬다운 코드를 작성할 수 있다.