개발 공부/Python

07_파이썬의 핵심 자료구조: 리스트, 튜플, 딕셔너리 총정리

squareegg 2025. 6. 9. 09:47

파이썬에서 데이터를 효율적으로 관리하고 처리하기 위해서는 리스트(List), 튜플(Tuple), **딕셔너리(Dictionary)**의 개념과 차이를 정확히 이해하는 것이 필수입니다. 각각의 자료구조는 용도와 특징이 다르므로, 상황에 맞게 적절히 선택하여 활용해야 합니다.

1. 리스트 (List): 유연하고 강력한 데이터 목록

기본 개념

  • 정의: 여러 개의 데이터를 순서대로 저장하는 자료구조
  • 기호: 대괄호 [ ] 사용
  • 특징:
    • 순서(인덱스)가 있음: 0번부터 시작하는 인덱스로 각 요소에 접근
    • 수정, 추가, 삭제 가능: mutable(변경 가능) 자료형
    • 중복 허용
    • 다양한 데이터형 혼합 가능

리스트 생성과 특징

# 리스트는 대괄호[]로 생성한다
fruits = ['apple', 'banana', 'cherry']

# 파이썬의 리스트는 다른 프로그래밍 언어의 배열과 달리 다양한 데이터형을 섞을 수 있다
mixed_list = [1, 'hello', 3.14, True, [1, 2, 3]]

print(mixed_list)  # [1, 'hello', 3.14, True, [1, 2, 3]]

리스트 접근과 조작

# 리스트는 음수값으로 접근할 수 있다
# 첨자는 맨 뒤에서부터 -1값으로 사용되는 것을 확인할 수 있다
fruits = ['apple', 'banana', 'cherry', 'date']
print(fruits[0])   # 'apple' (첫 번째)
print(fruits[-1])  # 'date' (마지막)
print(fruits[-2])  # 'cherry' (뒤에서 두 번째)

# 리스트에 접근할 때 콜론을 사용해 범위를 지정할 수 있다
# '리스트명[시작값:끝값+1]' 형식
print(fruits[1:3])  # ['banana', 'cherry']
print(fruits[:2])   # ['apple', 'banana'] (처음부터 1번까지)
print(fruits[2:])   # ['cherry', 'date'] (2번부터 끝까지)

# 리스트의 항목을 건너뛰며 추출할 수 있다 [::2] [::-2]
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(numbers[::2])   # [0, 2, 4, 6, 8] (2칸씩 건너뛰기)
print(numbers[::-1])  # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] (역순)
print(numbers[::-2])  # [9, 7, 5, 3, 1] (역순으로 2칸씩)

# 값 수정
fruits[1] = 'orange'
print(fruits)  # ['apple', 'orange', 'cherry', 'date']

# 값 추가
fruits.append('grape')  # 끝에 추가
fruits.insert(1, 'kiwi')  # 특정 위치에 추가

# 리스트의 항목을 삭제하려면 del() 함수를 사용
del fruits[0]  # 인덱스로 삭제
fruits.remove('orange')  # 값으로 삭제
last_fruit = fruits.pop()  # 마지막 요소 제거하고 반환

리스트 삭제 방법들

my_list = [1, 2, 3, 4, 5]

# 방법 1: 리스트 내용을 모두 삭제해 빈 리스트로 만든다
my_list.clear()  # 또는 my_list = []
print(my_list)  # []

# 방법 2: 리스트에 None값을 넣어 빈 변수로 만든다
my_list = None
print(my_list)  # None

# 방법 3: 변수를 삭제한다
del my_list
# print(my_list)  # NameError 발생

리스트의 고급 활용법

1. 리스트 슬라이싱

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

print(numbers[2:5])    # [2, 3, 4] - 2번부터 4번까지
print(numbers[:3])     # [0, 1, 2] - 처음부터 2번까지
print(numbers[7:])     # [7, 8, 9] - 7번부터 끝까지
print(numbers[::2])    # [0, 2, 4, 6, 8] - 2칸씩 건너뛰기
print(numbers[::-1])   # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - 역순

2. 리스트 컴프리헨션 (List Comprehension)

# 1부터 10까지의 제곱수 만들기
squares = [x**2 for x in range(1, 11)]
print(squares)  # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

# 조건부 리스트 컴프리헨션
even_squares = [x**2 for x in range(1, 11) if x % 2 == 0]
print(even_squares)  # [4, 16, 36, 64, 100]

3. 리스트 조작 함수들과 정렬

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

# 리스트 조작 함수들
my_list = [1, 2, 3]
my_list.append(4)     # 끝에 추가: [1, 2, 3, 4]
removed = my_list.pop()  # 마지막 요소 제거하고 반환: 4
my_list.extend([5, 6])   # 여러 요소 추가: [1, 2, 3, 5, 6]

# 정렬: 리스트.sort()와 sorted(리스트)의 차이
original = [3, 1, 4, 1, 5]
original.sort()  # 원본 리스트를 직접 수정
print(original)  # [1, 1, 3, 4, 5]

original2 = [3, 1, 4, 1, 5]
sorted_list = sorted(original2)  # 새로운 정렬된 리스트 반환
print(original2)    # [3, 1, 4, 1, 5] (원본 유지)
print(sorted_list)  # [1, 1, 3, 4, 5]

# 개수 세기
print(numbers.count(1))  # 2

# 위치 찾기
print(numbers.index(4))  # 2

# 리스트 합치기
list1 = [1, 2, 3]
list2 = [4, 5, 6]
combined = list1 + list2  # [1, 2, 3, 4, 5, 6]
list1.extend(list2)  # list1에 list2 추가

4. 2차원 리스트

# 2차원 리스트에서 각 항목에 접근하려면 [0][0]처럼 첨자를 2개 사용해야 한다
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print(matrix[0][0])  # 1 (첫 번째 행, 첫 번째 열)
print(matrix[1][2])  # 6 (두 번째 행, 세 번째 열)

# 리스트의 각 열의 크기를 다르게 생성할 수도 있다
irregular_matrix = [[1, 2], [3, 4, 5, 6], [7]]
print(irregular_matrix[1][3])  # 6

5. 리스트와 반복문 활용

# 리스트는 단독으로 사용하기보다는 대개 for문이나 while문과 함께 사용한다
fruits = ['apple', 'banana', 'cherry']

# for문과 함께 사용
for fruit in fruits:
    print(f"I like {fruit}")

# 인덱스와 함께 사용
for i, fruit in enumerate(fruits):
    print(f"{i}: {fruit}")

# while문과 함께 사용
i = 0
while i < len(fruits):
    print(fruits[i])
    i += 1
더보기

✅ 리스트 주요 메서드 정리표

 
메서드 설명  예시
append(x) 리스트 끝에 요소 추가 lst.append(5)
extend(iter) iterable 요소를 리스트에 추가 lst.extend([4, 5])
insert(i, x) i번째 위치에 x 삽입 lst.insert(1, 100)
remove(x) x를 찾아 첫 번째 요소 삭제 lst.remove(3)
pop([i]) i번째 요소 제거 후 반환 (기본: 마지막) lst.pop()
clear() 모든 요소 삭제 lst.clear()
index(x) x의 첫 번째 인덱스 반환 lst.index(2)
count(x) x의 개수 반환 lst.count(1)
sort() 리스트 정렬 (기본 오름차순) lst.sort()
sorted(iter) 정렬된 리스트 반환 (원본 유지) sorted(lst)
reverse() 리스트 순서를 반대로 뒤집음 lst.reverse()
copy() 리스트의 얕은 복사본 생성 lst2 = lst.copy()

2. 튜플 (Tuple): 수정 불가, 읽기 전용 데이터 목록

기본 개념

  • 정의: 리스트와 비슷하지만, 한 번 생성하면 값을 변경할 수 없는 자료구조
  • 기호: 소괄호 ( ) 사용
  • 특징:
    • 순서(인덱스)가 있음
    • 수정, 추가, 삭제 불가: immutable(불변) 자료형
    • 중복 허용
    • 다양한 데이터형 혼합 가능

튜플 생성과 특징

# 튜플은 소괄호()로 생성한다
point = (10, 20)
colors = ('red', 'green', 'blue')
mixed_tuple = (1, 'hello', 3.14, True)

# 항목이 하나인 튜플은 뒤에 쉼표(,)를 붙여야 한다
single = (42,)  # 또는 42,
not_tuple = (42)  # 이것은 그냥 정수 42

print(type(single))     # <class 'tuple'>
print(type(not_tuple))  # <class 'int'>

# 값 접근 (읽기만 가능해 읽기전용 자료를 저장할 때 사용한다)
print(point[0])  # 10
print(colors[-1])  # 'blue'

# 튜플의 값을 수정할 수 없다
# point[0] = 30  # TypeError: 'tuple' object does not support item assignment

튜플 연산과 변환

# 튜플의 덧셈 및 곱셈 연산도 가능하다
tuple1 = (1, 2, 3)
tuple2 = (4, 5, 6)
combined = tuple1 + tuple2  # (1, 2, 3, 4, 5, 6)
repeated = tuple1 * 3       # (1, 2, 3, 1, 2, 3, 1, 2, 3)

# 자료형 변환
my_list = [1, 2, 3, 4]
my_tuple = (1, 2, 3, 4)

# list(튜플) 함수는 튜플을 리스트로 변환
converted_list = list(my_tuple)
print(converted_list)  # [1, 2, 3, 4]

# tuple(리스트) 함수는 리스트를 튜플로 변환
converted_tuple = tuple(my_list)
print(converted_tuple)  # (1, 2, 3, 4)

# 튜플 자체는 del() 함수로 삭제할 수 있다
temp_tuple = (1, 2, 3)
del temp_tuple
# print(temp_tuple)  # NameError 발생

튜플의 고급 활용법

1. 튜플 언패킹 (Unpacking)

# 좌표 언패킹
point = (10, 20)
x, y = point
print(f"x: {x}, y: {y}")  # x: 10, y: 20

# 여러 값 동시 할당
person = ('Alice', 25, 'Engineer')
name, age, job = person

# 값 교환
a, b = 1, 2
a, b = b, a  # a=2, b=1

2. 함수에서 여러 값 반환

def get_name_age():
    return "Bob", 30

def calculate_stats(numbers):
    return min(numbers), max(numbers), sum(numbers)/len(numbers)

name, age = get_name_age()
min_val, max_val, avg = calculate_stats([1, 2, 3, 4, 5])

3. 딕셔너리의 items()와 함께 사용

student_grades = {'Alice': 85, 'Bob': 92, 'Charlie': 78}

for name, grade in student_grades.items():
    print(f"{name}: {grade}")

3. 딕셔너리 (Dictionary): 키-값 쌍의 집합

기본 개념

  • 정의: 키(key)와 값(value)의 쌍으로 데이터를 저장하는 자료구조
  • 기호: 중괄호 { } 사용, 키:값 쌍으로 구성
  • 특징:
    • 순서 없음(파이썬 3.7 이후 삽입 순서 유지)
    • 키로 값에 접근 (인덱스 대신 키 사용)
    • 수정, 추가, 삭제 가능: mutable
    • 키는 중복 불가, 값은 중복 허용

딕셔너리 생성과 기본 조작

# 딕셔너리는 {} 중괄호로 묶어 구성
# 키(key)와 값(value)의 쌍으로 구성
student = {'name': 'Alice', 'age': 20, 'major': 'CS'}
empty_dict = {}  # 또는 dict()

# '딕셔너리명[키] = 값' 형식으로 쌍을 추가할 수 있다
student['grade'] = 'A'
print(student)  # {'name': 'Alice', 'age': 20, 'major': 'CS', 'grade': 'A'}

# 이미 존재하는 키를 사용하면 기존값이 변경
student['age'] = 21  # 기존 'age' 값 수정
print(student['age'])  # 21

# 키는 유일해야 함 (중복된 키는 마지막 값으로 덮어짐)
duplicate_key_dict = {'name': 'Alice', 'name': 'Bob'}
print(duplicate_key_dict)  # {'name': 'Bob'}

# 'del(딕셔너리명[키])' 형식으로 삭제 가능
del student['major']
print(student)  # {'name': 'Alice', 'age': 21, 'grade': 'A'}

딕셔너리 값 접근 방법

student = {'name': 'Alice', 'age': 20, 'major': 'CS'}

# 딕셔너리명.get(키) 함수를 사용해 값에 접근
name1 = student['name']        # 'Alice'
name2 = student.get('name')    # 'Alice'

# 딕셔너리명[키]와 딕셔너리명.get(키)는 결과가 같다
print(name1 == name2)  # True

# 차이점: 없는 키 접근 시 동작
# 딕셔너리명[키]는 없는 키를 호출하면 오류가 나지만
try:
    print(student['grade'])  # KeyError 발생
except KeyError:
    print("KeyError 발생!")

# 딕셔너리명.get(키)는 없는 키를 호출하면 None을 반환한다
grade = student.get('grade')
print(grade)  # None

# 기본값 설정도 가능
grade_with_default = student.get('grade', 'N/A')
print(grade_with_default)  # 'N/A'

딕셔너리 메서드들

student = {'name': 'Alice', 'age': 20, 'major': 'CS'}

# 딕셔너리명.keys()는 딕셔너리의 모든 키를 반환
keys = student.keys()
print(keys)  # dict_keys(['name', 'age', 'major'])

# 출력 결과의 dict_keys가 보기 싫으면 list(딕셔너리명.keys()) 함수를 사용
keys_list = list(student.keys())
print(keys_list)  # ['name', 'age', 'major']

# 딕셔너리명.values() 함수는 딕셔너리의 모든 값을 리스트로 만들어 반환
values = student.values()
print(values)  # dict_values(['Alice', 20, 'CS'])
values_list = list(student.values())
print(values_list)  # ['Alice', 20, 'CS']

# 딕셔너리명.items() 함수를 사용하면 키와 값의 쌍을 튜플 형태로 구현 가능
items = student.items()
print(items)  # dict_items([('name', 'Alice'), ('age', 20), ('major', 'CS')])

# 딕셔너리 안에 해당 키가 있는지 없는지는 in을 사용해 확인할 수 있다
print('name' in student)     # True
print('grade' in student)    # False
print('Alice' in student.values())  # True

딕셔너리의 고급 활용법

1. 딕셔너리 메서드들

student = {'name': 'Alice', 'age': 20, 'major': 'CS'}

# 모든 키, 값, 키-값 쌍 가져오기
print(student.keys())    # dict_keys(['name', 'age', 'major'])
print(student.values())  # dict_values(['Alice', 20, 'CS'])
print(student.items())   # dict_items([('name', 'Alice'), ('age', 20), ('major', 'CS')])

# 딕셔너리 병합 (Python 3.9+)
defaults = {'grade': 'N/A', 'status': 'active'}
student = defaults | student  # 또는 student.update(defaults)

2. 딕셔너리 컴프리헨션

# 숫자와 제곱수 딕셔너리
squares = {x: x**2 for x in range(1, 6)}
print(squares)  # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

# 조건부 딕셔너리 컴프리헨션
even_squares = {x: x**2 for x in range(1, 11) if x % 2 == 0}
print(even_squares)  # {2: 4, 4: 16, 6: 36, 8: 64, 10: 100}

3. 중첩 딕셔너리 활용

# 학생 정보 관리
students = {
    'Alice': {'age': 20, 'grade': 'A', 'subjects': ['Math', 'Physics']},
    'Bob': {'age': 22, 'grade': 'B', 'subjects': ['Chemistry', 'Biology']}
}

# 중첩 딕셔너리 접근
print(students['Alice']['grade'])  # 'A'
print(students['Bob']['subjects'][0])  # 'Chemistry'
더보기

✅ 딕셔너리 주요 메서드 정리표

메서드 설명 예시
keys() 모든 키 반환 student.keys()
values() 모든 값 반환 student.values()
items() (키, 값) 쌍 반환 student.items()
get(key) 키의 값 반환 (없으면 None) student.get("age")
update({...}) 값 수정 또는 키-값 추가 student.update({"grade": 3})
pop(key) 키-값 삭제 후 값 반환 student.pop("major")
clear() 모든 항목 제거 student.clear()
in 연산자 키 존재 여부 확인 'name' in student
setdefault() 키가 없으면 추가, 있으면 그대로 반환 student.setdefault("club", "AI Lab")

4. 세트 (Set): 중복 없는 데이터 집합

기본 개념

  • 정의: 중복 없는 데이터의 집합
  • 기호: 중괄호 { } 사용, 값만 입력
  • 특징:
    • 순서 없음
    • 중복 불가
    • 수정(추가/삭제) 가능, 값 변경 불가
    • 인덱싱 불가

세트의 기본 개념과 생성

# 세트(set)는 키만 모아놓은 딕셔너리의 특수한 형태이다
numbers = {1, 2, 3, 3, 4}
print(numbers)  # {1, 2, 3, 4} - 중복 자동 제거

# 빈 세트를 만들 때는 s = set() 구문을 사용
# s = {} 구문을 쓰면 빈 딕셔너리로 인식
empty_set = set()
empty_dict = {}
print(type(empty_set))   # <class 'set'>
print(type(empty_dict))  # <class 'dict'>

# set() 함수는 리스트, 튜플, 딕셔너리들을 세트로 변경시켜준다
list_to_set = set([1, 2, 2, 3, 3, 4])
print(list_to_set)  # {1, 2, 3, 4}

tuple_to_set = set((1, 2, 3, 3, 4))
print(tuple_to_set)  # {1, 2, 3, 4}

dict_to_set = set({'a': 1, 'b': 2, 'c': 3})  # 키만 추출
print(dict_to_set)  # {'a', 'b', 'c'}

# 리스트에서 중복 제거
list_with_duplicates = [1, 2, 2, 3, 3, 3, 4]
unique_numbers = list(set(list_with_duplicates))
print(unique_numbers)  # [1, 2, 3, 4] (순서는 보장되지 않음)

세트의 집합 연산

# 집합 연산 (메서드와 연산자 두 가지 방법)
set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}

# 합집합 (union)
print(set1 | set2)           # {1, 2, 3, 4, 5, 6}
print(set1.union(set2))      # {1, 2, 3, 4, 5, 6}

# 교집합 (intersection)
print(set1 & set2)              # {3, 4}
print(set1.intersection(set2))  # {3, 4}

# 차집합 (difference)
print(set1 - set2)             # {1, 2}
print(set1.difference(set2))   # {1, 2}

# 대칭차집합 (symmetric_difference)
print(set1 ^ set2)                        # {1, 2, 5, 6}
print(set1.symmetric_difference(set2))    # {1, 2, 5, 6}

# 세트 요소 추가/제거
my_set = {1, 2, 3}
my_set.add(4)        # 요소 추가
my_set.remove(2)     # 요소 제거 (없으면 오류)
my_set.discard(5)    # 요소 제거 (없어도 오류 없음)
print(my_set)        # {1, 3, 4}
더보기

✅ zip() 함수

  • 여러 개의 iterable을 병렬로 묶어줌
  • 주로 for문에서 많이 사용됨
names = ['Tom', 'Jane', 'Mike']
scores = [90, 85, 95]

for name, score in zip(names, scores):
    print(f'{name}의 점수는 {score}점입니다.')


✅ 얕은 복사 vs 깊은 복사

구분  설명 예시
얕은 복사 참조만 복사하여 원본과 연결됨 copy_list = original_list
깊은 복사 객체 전체를 새롭게 복사하여 독립적인 객체 생성 import copycopy.deepcopy(original_list)
import copy

# 얕은 복사
a = [1, 2, [3, 4]]
b = a
b[2][0] = 99
print(a)  # [1, 2, [99, 4]]

# 깊은 복사
c = copy.deepcopy(a)
c[2][0] = 3
print(a)  # [1, 2, [99, 4]]
print(c)  # [1, 2, [3, 4]]

5. 실전 활용 예제

예제 1: 학생 성적 관리 시스템

# 딕셔너리와 리스트를 활용한 성적 관리
class GradeManager:
    def __init__(self):
        self.students = {}
    
    def add_student(self, name, *grades):
        self.students[name] = list(grades)
    
    def add_grade(self, name, grade):
        if name in self.students:
            self.students[name].append(grade)
    
    def get_average(self, name):
        if name in self.students and self.students[name]:
            return sum(self.students[name]) / len(self.students[name])
        return 0
    
    def get_top_students(self, n=3):
        averages = [(name, self.get_average(name)) for name in self.students]
        return sorted(averages, key=lambda x: x[1], reverse=True)[:n]

# 사용 예시
gm = GradeManager()
gm.add_student('Alice', 85, 92, 78)
gm.add_student('Bob', 90, 88, 94)
gm.add_grade('Alice', 95)

print(f"Alice 평균: {gm.get_average('Alice'):.2f}")
print("상위 학생들:", gm.get_top_students())

예제 2: 단어 빈도 분석

def analyze_text(text):
    # 단어 분리 및 소문자 변환
    words = text.lower().replace(',', '').replace('.', '').split()
    
    # 딕셔너리로 단어 빈도 계산
    word_count = {}
    for word in words:
        word_count[word] = word_count.get(word, 0) + 1
    
    # 가장 많이 사용된 단어들
    sorted_words = sorted(word_count.items(), key=lambda x: x[1], reverse=True)
    
    return {
        'total_words': len(words),
        'unique_words': len(word_count),
        'most_common': sorted_words[:5],
        'word_frequencies': word_count
    }

text = "Python is great. Python is powerful. Programming with Python is fun."
result = analyze_text(text)
print(f"총 단어 수: {result['total_words']}")
print(f"고유 단어 수: {result['unique_words']}")
print("가장 자주 사용된 단어들:", result['most_common'])

6. 자료구조 비교 표


자료구조 기호 순서 중복 변경 인덱스/키 대표 메서드/연산
리스트 [ ] O O O 인덱스 append, pop, sort
튜플 ( ) O O X 인덱스 count, index
딕셔너리 { } X 값O O keys, values, items
세트 { } X X O X add, remove, union, intersection

7. 성능 비교와 선택 기준

시간 복잡도 비교

  • 리스트:
    • 접근: O(1), 검색: O(n), 삽입/삭제: O(n)
  • 튜플:
    • 접근: O(1), 검색: O(n)
  • 딕셔너리:
    • 접근/삽입/삭제: 평균 O(1)
  • 세트:
    • 검색/삽입/삭제: 평균 O(1)

언제 어떤 자료구조를 써야 할까?

리스트 사용 시기:

  • 순서가 중요한 데이터 저장
  • 동일한 값이 여러 번 필요
  • 데이터의 추가/수정/삭제가 빈번
  • 인덱스로 빠른 접근이 필요

튜플 사용 시기:

  • 변경되지 않아야 하는 데이터
  • 함수에서 여러 값 반환
  • 딕셔너리의 키로 사용 (immutable이므로)
  • 좌표, 색상값 등 고정된 데이터

딕셔너리 사용 시기:

  • 키-값 쌍으로 데이터 관리
  • 빠른 검색이 필요
  • 데이터에 의미있는 이름 부여
  • 설정 정보, 매핑 데이터 저장

세트 사용 시기:

  • 중복 제거가 필요
  • 집합 연산 (합집합, 교집합 등) 수행
  • 멤버십 테스트가 빈번
  • 고유한 값들만 저장

8. 마무리

파이썬의 핵심 자료구조들은 각각 고유한 특성과 장점을 가지고 있습니다. 효율적인 파이썬 프로그래밍을 위해서는:

  1. 각 자료구조의 특성을 정확히 이해하고
  2. 상황에 맞는 적절한 선택을 하며
  3. 고급 기능들을 활용하여 코드를 간결하고 효율적으로 작성해야 합니다

이러한 자료구조들을 잘 활용하면 복잡한 데이터 처리도 간단하고 직관적으로 해결할 수 있으며, 파이썬의 진정한 힘을 경험할 수 있을 것입니다!

더보기

파이썬 자료구조 시험 대비 핵심 요약 📚

🎯 시험 출제 포인트 요약

1. 자료구조 기본 특징 (암기 필수!)

자료구조 기호 순서 중복 변경가능 접근방법 특징
리스트 [ ] 인덱스 mutable, 다양한 데이터형 혼합
튜플 ( ) 인덱스 immutable, 읽기전용
딕셔너리 { } 값⭕키❌ 키-값 쌍, 키는 유일
세트 { } - 중복제거, 집합연산

2. 시험 단골 문제 유형

⚠️ 자주 틀리는 포인트들

# 1. 빈 자료구조 생성
empty_list = []          # 리스트
empty_tuple = ()         # 튜플  
empty_dict = {}          # 딕셔너리
empty_set = set()        # 세트 (주의: {}는 딕셔너리!)

# 2. 단일 요소 튜플
single_tuple = (5,)      # 쉼표 필수!
# single_tuple = (5)     # 이건 그냥 정수 5

# 3. 음수 인덱싱
lst = [1, 2, 3, 4, 5]
print(lst[-1])           # 5 (마지막)
print(lst[-2])           # 4 (뒤에서 두번째)

# 4. 딕셔너리 접근법 차이
student = {'name': 'Alice'}
print(student['name'])         # 'Alice'
print(student.get('name'))     # 'Alice'
print(student['age'])          # KeyError 발생!
print(student.get('age'))      # None 반환

📋 함수/메서드 완전 정리

리스트 메서드 (시험 필수!)

메서드 기능 예시 반환값 원본변경
append(x) 끝에 요소 추가 lst.append(5) None
insert(i, x) i위치에 x 삽입 lst.insert(0, 'first') None
remove(x) 첫번째 x 제거 lst.remove('apple') None
pop() 마지막 요소 제거&반환 item = lst.pop() 제거된 요소
pop(i) i위치 요소 제거&반환 item = lst.pop(0) 제거된 요소
index(x) x의 첫번째 인덱스 idx = lst.index('apple') 인덱스
count(x) x의 개수 cnt = lst.count(5) 개수
sort() 정렬 (오름차순) lst.sort() None
sort(reverse=True) 내림차순 정렬 lst.sort(reverse=True) None
reverse() 순서 뒤집기 lst.reverse() None
clear() 모든 요소 제거 lst.clear() None
copy() 얕은 복사 new_lst = lst.copy() 새 리스트
extend()        
len()        
sorted()        

⚡ 시험 TIP: sort() vs sorted() 구분!

lst = [3, 1, 4]
lst.sort()              # 원본 변경, None 반환
new_lst = sorted(lst)   # 원본 유지, 새 리스트 반환

튜플 메서드

메서드 기능 예시 반환값
count(x) x의 개수 tup.count(5) 개수
index(x) x의 첫번째 인덱스 tup.index('apple') 인덱스

💡 튜플 변환

tuple_to_list = list(tup)    # 튜플 → 리스트
list_to_tuple = tuple(lst)   # 리스트 → 튜플

딕셔너리 메서드 (시험 중요!)

메서드 기능 예시 반환값 원본변경
get(key) 키의 값 반환 (없으면 None) dic.get('name') 값 또는 None
get(key, default) 키의 값 반환 (없으면 기본값) dic.get('age', 0) 값 또는 기본값
keys() 모든 키 반환 dic.keys() dict_keys 객체
values() 모든 값 반환 dic.values() dict_values 객체
items() 키-값 쌍들 반환 dic.items() dict_items 객체
pop(key) 키 제거 & 값 반환 val = dic.pop('name') 제거된 값
clear() 모든 항목 제거 dic.clear() None
update(other) 딕셔너리 병합 dic.update({'age': 20}) None

⚡ 시험 단골: dic['key'] vs dic.get('key')

# 없는 키 접근 시
dic['nonexistent']     # KeyError 발생!
dic.get('nonexistent') # None 반환 (오류 없음)

세트 메서드

메서드 기능 예시 반환값 원본변경
add(x) 요소 추가 s.add(5) None
remove(x) 요소 제거 (없으면 오류) s.remove(5) None
discard(x) 요소 제거 (없어도 오류 없음) s.discard(5) None
pop() 임의 요소 제거&반환 item = s.pop() 제거된 요소
clear() 모든 요소 제거 s.clear() None

 

집합 연산 메서드

메서드 연산자 기능 예시
union(other) | 합집합 s1.union(s2) 또는 s1 | s2
intersection(other) & 교집합 s1.intersection(s2) 또는 s1 & s2
difference(other) - 차집합 s1.difference(s2) 또는 s1 - s2
symmetric_difference(other) ^ 대칭차집합 s1.symmetric_difference(s2) 또는 s1 ^ s2

🔥 시험 출제 예상 문제 유형

1. 슬라이싱 (90% 출제!)

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

# 기본 슬라이싱
lst[2:5]     # [2, 3, 4]
lst[:3]      # [0, 1, 2]
lst[5:]      # [5, 6, 7, 8, 9]
lst[:]       # 전체 복사

# 간격 슬라이싱
lst[::2]     # [0, 2, 4, 6, 8] (2칸씩)
lst[1::2]    # [1, 3, 5, 7, 9] (1부터 2칸씩)
lst[::-1]    # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] (역순)
lst[::-2]    # [9, 7, 5, 3, 1] (역순으로 2칸씩)

2. 2차원 리스트 접근

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

matrix[0][0]    # 1 (첫번째 행, 첫번째 열)
matrix[1][2]    # 6 (두번째 행, 세번째 열)
matrix[-1][-1]  # 9 (마지막 행, 마지막 열)

3. 컴프리헨션 (자주 출제!)

# 리스트 컴프리헨션
squares = [x**2 for x in range(5)]        # [0, 1, 4, 9, 16]
evens = [x for x in range(10) if x % 2 == 0]  # [0, 2, 4, 6, 8]

# 딕셔너리 컴프리헨션
square_dict = {x: x**2 for x in range(5)}  # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

# 세트 컴프리헨션
unique_squares = {x**2 for x in range(-3, 4)}  # {0, 1, 4, 9}

4. 자료구조 변환

# 문자열 → 리스트
list("hello")        # ['h', 'e', 'l', 'l', 'o']

# 리스트 → 문자열
"".join(['h', 'e'])  # "he"

# 중복 제거
unique_list = list(set([1, 2, 2, 3, 3]))  # [1, 2, 3]

# 리스트 → 딕셔너리 (zip 사용)
keys = ['a', 'b', 'c']
values = [1, 2, 3]
dict(zip(keys, values))  # {'a': 1, 'b': 2, 'c': 3}

🎲 스택/큐 구현 (실습 문제 단골!)

스택 (LIFO - Last In First Out)

stack = []

# Push (삽입)
stack.append(1)
stack.append(2)
stack.append(3)

# Pop (제거)
top = stack.pop()    # 3 (마지막에 들어간 것부터)

큐 (FIFO - First In First Out)

from collections import deque
queue = deque()

# Enqueue (삽입)
queue.append(1)
queue.append(2)
queue.append(3)

# Dequeue (제거)
front = queue.popleft()  # 1 (먼저 들어간 것부터)

🚨 시험 직전 체크리스트

암기 필수 사항

  1. 빈 자료구조: [], (), {}, set()
  2. 단일 튜플: (5,) (쉼표 필수!)
  3. 음수 인덱싱: -1이 마지막 요소
  4. 딕셔너리 접근: dict['key'] vs dict.get('key')
  5. 집합 연산: |(합), &(교), -(차), ^(대칭차)

함수 vs 메서드 구분

# 함수 (새로운 객체 반환, 원본 유지)
sorted(lst)    # 정렬된 새 리스트
list(tup)      # 튜플을 리스트로 변환
set(lst)       # 리스트를 세트로 변환

# 메서드 (원본 객체 변경)
lst.sort()     # 원본 리스트 정렬
lst.append()   # 원본 리스트에 추가

시간 복잡도 (고급 과정)

  • 리스트: 인덱스 접근 O(1), 검색 O(n)
  • 딕셔너리: 키 접근 O(1), 검색 O(1)
  • 세트: 멤버십 테스트 O(1)

💡 마지막 당부

  1. 실제 코드 작성 연습: 이론만 외우지 말고 직접 타이핑해보기
  2. 에러 메시지 익히기: KeyError, IndexError 등 자주 나오는 에러들
  3. 예외 상황 체크: 빈 리스트에서 pop(), 없는 키 접근 등
  4. 출력 결과 예측: 코드 보고 출력값 맞추는 연습

🔥 시험 직전 마지막 점검: 이 요약본을 시험 30분 전에 한 번 더 훑어보세요!

728x90
반응형