콘텐츠로 이동

8장: Collections — 여러 값을 담는 자료형

왜 여러 값을 담는 자료형이 필요한가?

학생 5명의 점수를 저장하려면 어떻게 할까요?

# 변수를 따로따로 만들면?
score1 = 90
score2 = 85
score3 = 78
score4 = 92
score5 = 88

학생이 100명이면 변수를 100개 만들어야 합니다. 번거롭고, 반복문과도 연결되지 않습니다.

# 리스트 하나면 충분
scores = [90, 85, 78, 92, 88]

Python은 여러 값을 하나의 이름으로 묶는 네 가지 자료형을 제공합니다.

iamList  = ["Kor", "Math", "Eng", "Sci"]          # list
iamTuple = ("Kor", "Math", "Eng", "Sci")           # tuple
iamSet   = {"Apple", "Banana", "Orange", "Apricot"} # set
iamDic   = {"Apple":150, "Banana":200, "Orange":45, "Apricot":40}  # dict
자료형 특징 예시
list 순서 있음, 값 변경 가능 [1, 2, 3]
tuple 순서 있음, 값 변경 불가 (1, 2, 3)
set 순서 없음, 중복 제거 {1, 2, 3}
dict 키–값 쌍, 키로 접근 {"name": "지민"}

리스트 (List)

리스트 만들기

대괄호 []로 만들고, 쉼표로 요소를 구분합니다.

fruits = ["apple", "banana", "cherry"]
numbers = [10, 20, 30, 40, 50]
mixed = [1, "hello", True, 3.14]   # 다른 타입도 섞을 수 있음
empty = []                          # 빈 리스트

인덱싱 (Indexing)

인덱스(위치 번호)로 요소에 접근합니다. 인덱스는 0부터 시작합니다.

fruits = ["apple", "banana", "cherry"]
#           0         1         2       (앞에서)
#          -3        -2        -1       (뒤에서)

print(fruits[0])    # apple
print(fruits[1])    # banana
print(fruits[-1])   # cherry  (마지막)
print(fruits[-2])   # banana  (뒤에서 두 번째)
apple
banana
cherry
banana

슬라이싱 (Slicing)

[시작:끝]으로 일부를 잘라냅니다. 끝 인덱스는 포함되지 않습니다.

nums = [0, 1, 2, 3, 4, 5]

print(nums[1:4])    # [1, 2, 3]   (인덱스 1, 2, 3)
print(nums[:3])     # [0, 1, 2]   (처음부터 인덱스 2까지)
print(nums[3:])     # [3, 4, 5]   (인덱스 3부터 끝까지)
print(nums[::2])    # [0, 2, 4]   (2칸씩 건너뜀)
print(nums[::-1])   # [5, 4, 3, 2, 1, 0]  (뒤집기)

리스트 수정

리스트는 변경 가능(mutable)합니다.

fruits = ["apple", "banana", "cherry"]

fruits[1] = "mango"         # 값 바꾸기
print(fruits)               # ['apple', 'mango', 'cherry']

주요 메서드

메서드 설명 예시
.append(x) 끝에 추가 lst.append(4)
.insert(i, x) 위치 i에 삽입 lst.insert(1, 99)
.remove(x) 값 x 제거 (첫 번째) lst.remove(2)
.pop() 마지막 요소 꺼내기 lst.pop()
.pop(i) 인덱스 i 요소 꺼내기 lst.pop(0)
.sort() 오름차순 정렬 lst.sort()
.sort(reverse=True) 내림차순 정렬 lst.sort(reverse=True)
.reverse() 순서 뒤집기 lst.reverse()
.index(x) 값 x의 인덱스 반환 lst.index(3)
len(lst) 요소 개수 len(lst)
nums = [3, 1, 4, 1, 5]

nums.append(9)
print(nums)           # [3, 1, 4, 1, 5, 9]

nums.remove(1)        # 첫 번째 1만 제거
print(nums)           # [3, 4, 1, 5, 9]

last = nums.pop()
print(last)           # 9
print(nums)           # [3, 4, 1, 5]

nums.sort()
print(nums)           # [1, 3, 4, 5]

print(len(nums))      # 4

리스트 순회

scores = [90, 85, 78, 92, 88]

for score in scores:
    print(score)
90
85
78
92
88

인덱스와 값을 동시에 얻으려면 enumerate()를 씁니다.

fruits = ["apple", "banana", "cherry"]

for i, fruit in enumerate(fruits):
    print(i, fruit)
0 apple
1 banana
2 cherry

in 연산자

fruits = ["apple", "banana", "cherry"]

print("banana" in fruits)   # True
print("grape" in fruits)    # False

튜플 (Tuple)

튜플 만들기

소괄호 ()로 만들거나, 괄호 없이 쉼표만으로도 만들 수 있습니다.

point = (3, 7)
colors = ("red", "green", "blue")
single = (42,)     # 요소가 하나일 때는 반드시 쉼표 필요
no_paren = 1, 2, 3 # 괄호 없이도 튜플

주의: (42)는 int이고, (42,)가 튜플입니다.

print(type((42)))    # <class 'int'>
print(type((42,)))   # <class 'tuple'>

튜플은 변경 불가 (Immutable)

리스트와 달리, 한 번 만든 튜플은 수정할 수 없습니다.

point = (3, 7)
point[0] = 10    # TypeError: 'tuple' object does not support item assignment

인덱싱·슬라이싱은 리스트와 동일합니다.

colors = ("red", "green", "blue")

print(colors[0])      # red
print(colors[-1])     # blue
print(colors[1:])     # ('green', 'blue')
print(len(colors))    # 3

튜플 언패킹 (Unpacking)

튜플의 값을 여러 변수에 한 번에 대입합니다.

point = (3, 7)
x, y = point
print(x)    # 3
print(y)    # 7
# 변수 값 교환 — Python 관용적 방법
a = 10
b = 20
a, b = b, a      # 내부적으로 튜플 언패킹
print(a, b)      # 20 10

함수에서 여러 값 반환

함수가 여러 값을 반환할 때 내부적으로 튜플이 사용됩니다.

def min_max(nums):
    return min(nums), max(nums)   # 튜플로 반환

lo, hi = min_max([3, 1, 4, 1, 5, 9])
print(lo, hi)    # 1 9

list vs tuple

항목 list tuple
괄호 [] ()
변경 가능 불가
속도 상대적으로 느림 빠름
용도 추가·삭제가 필요한 경우 변하지 않는 좌표·설정값 등

셋 (Set)

셋 만들기

중괄호 {}로 만들지만 키:값 쌍이 없고, 중복이 자동으로 제거됩니다.

fruits = {"Apple", "Banana", "Orange", "Apricot"}
numbers = {1, 2, 2, 3, 3, 3}   # 중복 제거
print(numbers)                   # {1, 2, 3}

주의: {} 만 쓰면 빈 dict가 됩니다. 빈 set은 set()으로 만듭니다.

셋의 특징

  • 순서 없음: 인덱싱·슬라이싱 불가
  • 중복 없음: 같은 값은 한 번만 저장
  • 집합 연산 가능: 합집합(|), 교집합(&), 차집합(-)
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}

print(a | b)   # {1, 2, 3, 4, 5, 6}  합집합
print(a & b)   # {3, 4}              교집합
print(a - b)   # {1, 2}              차집합

list vs set

favorite_animal = ['cat', 'cat', 'python', 'dog', 'python', 'dog', 'dog']

# list → 중복 포함, 순서 유지
print(favorite_animal)         # ['cat', 'cat', 'python', ...]

# set → 중복 제거
print(set(favorite_animal))    # {'cat', 'dog', 'python'}

딕셔너리 (Dictionary)

list vs dict

list는 인덱스(위치 번호)로, dict는 키(이름)로 접근합니다.

listA = [100, 90, 80, 50]
dictA = {"Kor":60, "Eng":80, "Math":60, "Science":90}

# list 접근: listA[0], listA[1], listA[2], listA[3]
# dict 접근: dictA['Kor'], dictA['Eng'], dictA['Math'], dictA['Science']
List Dictionary
구조 Index → Element Key → Value
접근 listA[0] dictA['Kor']
용도 순서가 중요한 데이터 이름이 필요한 데이터
# list로 혈액형 빈도 → 어떤 인덱스가 어떤 혈액형인지 알기 어려움
b_type_list = ['A','AB','B','O','AB','O','B','O','O','O','B','A','B','AB','A']

# dict로 만들면 의미가 명확
b_type_dict = {'A':3, 'AB':3, 'B':4, 'O':5}

딕셔너리 만들기

중괄호 {}로 만들고, 키: 값 쌍을 쉼표로 구분합니다.

dict_name = {key1:value1, key2:value2, ..., keyN:valueN}
scores  = {'KOR':50, 'MATH':80, 'ENG':40, 'PROG':95}
student = {"name": "지민", "age": 17, "score": 92}
empty   = {}

키(key)는 보통 문자열, 값(value)은 어떤 타입이든 가능합니다.

값에 접근하기

student = {"name": "지민", "age": 17, "score": 92}

print(student["name"])     # 지민
print(student["score"])    # 92

없는 키를 사용하면 KeyError가 발생합니다. 안전하게 접근하려면 .get()을 씁니다.

print(student.get("grade"))          # None  (오류 없이 None 반환)
print(student.get("grade", "없음"))  # 없음  (기본값 지정)

값 추가·수정·삭제

student = {"name": "지민", "age": 17}

student["score"] = 92        # 새 키 추가
student["age"] = 18          # 기존 키 값 수정
del student["score"]         # 키 삭제

print(student)    # {'name': '지민', 'age': 18}

주요 메서드

메서드 설명 반환
.keys() 모든 키 dict_keys
.values() 모든 값 dict_values
.items() (키, 값) 쌍 dict_items
.get(k) 키 k의 값 (없으면 None)
.get(k, d) 키 k의 값 (없으면 d)
k in d 키 존재 여부 bool
scores = {'KOR':50, 'MATH':80, 'ENG':40, 'PROG':95}

print(scores.keys())    # dict_keys(['KOR', 'MATH', 'ENG', 'PROG'])
print(scores.values())  # dict_values([50, 80, 40, 95])
print(scores.items())   # dict_items([('KOR', 50), ('MATH', 80), ('ENG', 40), ('PROG', 95)])

Q1: 모든 과목명 출력

sum = 0
for i in scores.keys() :
    print(i)
# KOR
# MATH
# ENG
# PROG

Q2: 점수 평균 계산

sum = 0
for i in scores.values() :
    sum += i
print(sum/4)    # 66.25

딕셔너리 순회

student = {"name": "지민", "age": 17, "score": 92}

# 키만
for key in student:
    print(key)

# 키와 값 동시에
for key, value in student.items():
    print(key, ":", value)
name : 지민
age : 17
score : 92

list comprehension과 딕셔너리

dict.values()를 list comprehension과 함께 사용하면 값 목록을 쉽게 변환할 수 있습니다.

scores = {'KOR':50, 'MATH':80, 'ENG':40, 'PROG':95}

# 값만 list로
v_list = [x for x in scores.values()]
print(v_list)    # [50, 80, 40, 95]

# 70 이상이면 'Pass', 미만이면 'Fail'
result = ['Pass' if x >= 70 else 'Fail' for x in scores.values()]
print(result)    # ['Fail', 'Pass', 'Fail', 'Pass']

in 연산자

딕셔너리에서 in를 검색합니다.

student = {"name": "지민", "age": 17}

print("name" in student)     # True
print("score" in student)    # False
print("지민" in student)      # False  (값은 검색 안 함)

네 자료형 비교

항목 list tuple set dict
생성 [1, 2] (1, 2) {1, 2} {"k": "v"}
접근 인덱스 [0] 인덱스 [0] 불가 ["key"]
변경 가능 불가 가능 가능
순서 보장 O O X O (Python 3.7+)
중복 허용 허용 불가 키는 불가
주요 용도 목록 관리 불변 데이터 중복 제거·집합 연산 이름 있는 데이터

실습 미션

미션 1: 리스트 통계

아래 점수 리스트에서 최댓값, 최솟값, 합계, 평균을 출력하세요.

scores = [78, 92, 85, 90, 88, 76, 95]

# 여기에 코드 작성

# 최댓값: 95
# 최솟값: 76
# 합계: 604
# 평균: 86.28...

미션 2: 리스트 필터링

점수 리스트에서 80점 이상인 점수만 골라 새 리스트로 만드세요.

scores = [78, 92, 85, 90, 88, 76, 95]

# 여기에 코드 작성
# 결과: [92, 85, 90, 88, 95]

미션 3: 튜플 언패킹

(이름, 나이, 점수) 형태의 튜플 리스트를 순회하며 출력하세요.

students = [
    ("지민", 17, 92),
    ("수현", 16, 88),
    ("민준", 17, 95),
]

# 여기에 코드 작성
# 지민 (17세): 92점
# 수현 (16세): 88점
# 민준 (17세): 95점

미션 4: 딕셔너리 활용

아래 딕셔너리에서 점수가 90점 이상인 학생의 이름과 점수를 출력하세요.

grade_book = {
    "지민": 92,
    "수현": 88,
    "민준": 95,
    "하은": 79,
    "태양": 91,
}

# 여기에 코드 작성
# 지민: 92
# 민준: 95
# 태양: 91

미션 5: 딕셔너리 구축

학생 이름 리스트와 점수 리스트를 받아 딕셔너리로 합치세요. (zip() 활용)

names = ["지민", "수현", "민준"]
scores = [92, 88, 95]

# 여기에 코드 작성
# {'지민': 92, '수현': 88, '민준': 95}

핵심 요약

개념 설명
list [], 순서 있음, 변경 가능
tuple (), 순서 있음, 변경 불가
set {}, 순서 없음, 중복 제거
dict {}, 키–값 쌍, 키로 접근
인덱싱 lst[0], lst[-1] — 0부터, 음수는 뒤에서
슬라이싱 lst[1:4] — 끝 인덱스 미포함
.append() 리스트 끝에 추가
.sort() 리스트 정렬
튜플 언패킹 x, y = (3, 7)
.keys() / .values() / .items() 딕셔너리 키·값·쌍 순회
.get(k, d) KeyError 없이 안전하게 접근
list comprehension [x for x in d.values()]
in list/tuple/set: 값 검색, dict: 키 검색