
지난 포스팅에서는 파이썬의 변수와 기초 자료형에 대해서 알아봤는데요.
만약 자료형이 뭔지 모르신다면 앞의 포스팅 먼저 보시는 것을 추천드려요.
파이썬 기초 강의 2강 변수와 데이터 타입
지난 포스팅에서는 파이썬이 무엇이고 왜 배워야하는지 알려드렸습니다.만약 앞의 포스팅을 못보셨다면 먼저 보고 오시는 것을 추천드립니다. 파이썬 기초 강의 1강 파이썬이란?요즘 정말 핫
jaeyoon-95.tistory.com
이번 포스팅에서는 조금 더 심화된 파이썬의 자료구조에 대한 이야기를 해볼까 합니다.
끝까지 잘 따라와주시면 너무 좋을 것 같아요!
질문은 언제나 환영입니다.

자료구조란 무엇인가?
자료구조란 데이터를 효율적으로 저장하고 관리하는 하나의 방법을 의미하는데요.
파이썬에서는 이러한 자료 구조를 기본으로 제공합니다.
크게 리스트, 튜플, 딕셔너리, 셋 이렇게 네 가지로 분류할 수 있습니다.
| 자료구조 | 설명 | 예시 |
| List | 여러 개의 값을 저장할 수 있는 순서가 있는 자료형(수정 가능) | [“컴공누나”] |
| Tuple | 여러 개의 값을 저장할 수 있는 순서가 있는 자료형(수정 불가) | (“컴공누나”) |
| Dictionary | 키(key)와 값(value) 쌍으로 이루어진 자료형 | {“name”:”컴공누나”} |
| Set | 중복을 허용하지 않는 자료형 | {“컴공누나”} |
이제 위의 자료구조를 하나씩 살펴볼게요.
리스트(List)
리스트는 다양한 형태의 자료형을 저장할 수 있습니다.
저장된 데이터들은 순서가 존재하는데요. 때문에 index로 접근을 할 수 있습니다.
값의 추가, 수정, 삭제가 가능해서 비교적 자유로운 자료 구조라고 할 수 있습니다.
대괄호 []를 이용하여 데이터를 감싸는 형태로 정의하게 됩니다.
# 리스트 생성
fruits = ["사과", "바나나", "딸기"]
print(fruits) # ['사과', '바나나', '딸기']
# 요소 접근 (인덱싱)
print(fruits[0]) # '사과'
print(fruits[-1]) # '딸기' (음수 인덱스 사용 가능)
# 리스트 값 변경
fruits[1] = "오렌지"
print(fruits) # ['사과', '오렌지', '딸기']
# 요소 추가
fruits.append("포도") # 끝에 추가
fruits.insert(1, "망고") # 특정 위치에 추가
print(fruits) # ['사과', '망고', '오렌지', '딸기', '포도']
# 요소 삭제
fruits.remove("딸기") # 특정 값 제거
del fruits[0] # 특정 인덱스 삭제
print(fruits) # ['망고', '오렌지', '포도']
# 리스트 길이 확인
print(len(fruits)) # 3
앞의 포스팅에서 설명했던 자료형처럼 자료구조도 사용 가능한 연산자들이 있습니다.

단순히 +, *도 있지만, append()등의 함수도 있죠.
사용되는 코드는 아래의 예제에서 확인해볼게요!
# 리스트 생성
my_list = [3, 1, 4, 1, 5]
my_list = my_list + [9, 2, 6] # [3, 1, 4, 1, 5, 9, 2, 6]
my_list = my_list * 2 # [3, 1, 4, 1, 5, 9, 2, 6, 3, 1, 4, 1, 5, 9, 2, 6]
len(my_list) # 16
my_list.append(5) # [3, 1, 4, 1, 5, 9, 2, 6, 3, 1, 4, 1, 5, 9, 2, 6, 5]
my_list.insert(2, 8) # [3, 1, 8, 4, 1, 5, 9, 2, 6, 3, 1, 4, 1, 5, 9, 2, 6, 5]
my_list.remove(1) # [3, 8, 4, 1, 5, 9, 2, 6, 3, 1, 4, 1, 5, 9, 2, 6, 5]
popped_value = my_list.pop() # popped_value = 5
index_of_4 = my_list.index(4) # index_of_4 = 2
count_of_1 = my_list.count(1) # count_of_1 = 2
my_list.sort() # [1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 9, 9]
my_list.reverse() # [9, 9, 8, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1]
덧셈의 경우 단순히 두 리스트를 이어 붙이는 것을 알 수 있습니다.
곱셈의 경우 곱해진 수만큼 해당 리스트가 반복됩니다.
len의 경우 리스트 길이를 측정하는 함수로, len(A)처럼 사용합니다. A는 길이를 측정할 대상인 리스트입니다.
append(A)는 내에 있는 숫자 A는 리스트의 가장 마지막 부분에 추가됩니다.
insert(A, B)의 경우 A의 자리에 B의 값이 추가됩니다.
위의 예제는 인덱스 2번째 자리에 10이 추가된 것을 확인할 수 있죠.
remove(A)는 리스트 내에서 A의 값을 삭제해 줍니다. 단, 가장 앞에 있는 1개만 삭제됩니다.
pop()은 리스트의 가장 마지막에 있는 원소를 꺼내줍니다. 꺼내고 나면 리스트에 해당 값은 삭제됩니다.
index(A)는 리스트 내에 있는 A값의 인덱스를 찾는 함수입니다. 여러개일 경우 가장 첫 번째 값의 인덱스를 반환합니다.
count(A)는 리스트 내에 있는 숫자 A의 개수를 세줍니다.
sort()는 말 그대로 리스트를 정렬시켜주는데요.
오름차순의 경우 그대로 두시면 되고, 내림차순은 sort(reverse=True)로 사용 가능합니다.
reverse()는 현재 리스트를 반대로 뒤집는 함수입니다.
튜플(Tuple)
튜플은 리스트와 비슷하게 사용되지만, 굉장히 다른 자료구조입니다.
튜플은 값의 변경 자체가 불가능합니다. 따라서 데이터를 보호가 필요할 경우 사용됩니다.
한 가지 동일한 점은 값의 순서가 있기 때문에 index접근이 가능하다는 것입니다.
두 자료구조의 속도를 비교하자면 튜플이 조금 더 빠릅니다.
튜플은 소괄호 ()를 이용하여 데이터를 감싸는 형태로 정의합니다.
# 튜플 생성
colors = ("빨강", "초록", "파랑")
print(colors) # ('빨강', '초록', '파랑')
# 요소 접근 (인덱싱)
print(colors[1]) # '초록'
# 값 변경 시도 (오류 발생)
# colors[1] = "노랑" # ❌ TypeError: 'tuple' object does not support item assignment
# 요소 개수 확인
print(len(colors)) # 3
# 튜플에서 특정 값의 개수 찾기
print(colors.count("빨강")) # 1
위의 코드 예시에서 보시는 것 처럼 특정 값을 인덱스로 접근한 뒤 수정하려고하면 타입 에러가 납니다.
이제 튜플에서 사용 가능한 연산자를 살펴볼게요.

튜플은 비교적 간단한 연산자들이 있습니다.
# 튜플 생성
my_tuple = (3, 1, 4, 1, 5)
my_tuple = my_tuple + (9, 2, 6) # (3, 1, 4, 1, 5, 9, 2, 6)
my_tuple = my_tuple * 2 # (3, 1, 4, 1, 5, 9, 2, 6, 3, 1, 4, 1, 5, 9, 2, 6)
len(my_tuple) # 16
index_of_4 = my_tuple.index(4) # index_of_4 = 2
count_of_1 = my_tuple.count(1) # count_of_1 = 3
덧셈의 경우 위의 리스트랑 역할이 같습니다. 다른 튜플과 합해줍니다.
곱셉 연산자 같은 경우 리스트와 동일하게 반복해줍니다.
len(A)도 동일하게 길이를 측정해주는 함수인데, A가 Tuple입니다.
index(A)는 튜플 내 특정 값 A의 인덱스를 찾아줍니다. 여러 개 있을 경우 첫 번째 값의 위치를 반환합니다.
count(A)의 경우 튜플 내에 있는 A의 개수를 세줍니다.
딕셔너리(Dictionary)
키(Key)와 값(Value) 쌍으로 저장하는 자료구조입니다.
기존 리스트와 튜플과는 굉장히 다른 형태인데요. 가장 큰 차이점은 딕셔너리는 순서가 없다는 것입니다.
딕셔너리의 Key값은 중복될 수 없지만, Value는 중복될 수 있습니다.
딕셔너리 내에 있는 값들은 언제든지 수정 및 삭제할 수 있습니다.
표현 방법은 {Key:Value}입니다.
# 딕셔너리 생성
student = {"이름": "철수", "나이": 20, "학교": "파이썬고"}
print(student) # {'이름': '철수', '나이': 20, '학교': '파이썬고'}
# 특정 값 조회
print(student["이름"]) # '철수'
# 값 변경
student["나이"] = 21
print(student) # {'이름': '철수', '나이': 21, '학교': '파이썬고'}
# 새로운 키-값 추가
student["전공"] = "컴퓨터"
print(student) # {'이름': '철수', '나이': 21, '학교': '파이썬고', '전공': '컴퓨터'}
# 키 삭제
del student["학교"]
print(student) # {'이름': '철수', '나이': 21, '전공': '컴퓨터'}
# 딕셔너리의 모든 키와 값 조회
print(student.keys()) # dict_keys(['이름', '나이', '전공'])
print(student.values()) # dict_values(['철수', 21, '컴퓨터'])
위와 같이 초기 student 딕셔너리를 선언하고, 언제든지 특정 키에 대한 값을 변경할 수 있으며 추가, 삭제가 자유롭습니다.
이제 딕셔너리에서 사용 가능한 연산자를 살펴보겠습니다.

앞에서 못봤던 함수들이 굉장히 많죠.
# 딕셔너리 생성
my_dict = {"a": 1, "b": 2, "c": 3}
# len() : 딕셔너리 길이 반환 (키 개수)
len(my_dict) # 3
"a" in my_dict # True
"x" in my_dict # False
my_dict.keys() # dict_keys(['a', 'b', 'c'])
my_dict.values() # dict_values([1, 2, 3])
my_dict.items() # dict_items([('a', 1), ('b', 2), ('c', 3)])
my_dict.get("b") # 2
my_dict.get("x") # None / 없는 키일 경우 None 반환
my_dict.get("x", "기본값") # "기본값" / key가 없으면 "기본값"반환
popped_value = my_dict.pop("b") # popped_value = 2
my_dict.update({"d": 4, "e": 5}) # my_dict = {'a': 1, 'c': 3, 'd': 4, 'e': 5}
my_dict.clear() # my_dict = {}
len(A) 같은 경우 앞의 리스트, 튜플과 같은데요. 딕셔너리 A의 key-value쌍이 몇개인지 숫자를 세줍니다. A는 딕셔너리 입니다.
in은 함수가 아니고, 단순 key값이 포함되어 있는지 찾기 위해 사용합니다. 왼쪽은 찾고자 하는 key, 오른쪽엔 딕셔너리를 적으시면 됩니다.
keys()는 딕셔너리에 있는 모든 key값들을 반환합니다.
values()는 딕셔너리 내에 있는 모든 value값들을 반환합니다.
items()는 딕셔너리 내에 있는 key, value쌍을 반환합니다.
get(A)는 딕셔너리 내에 A라는 키값이 있는지 확인하고 그 값을 반환해줍니다. 없을 경우 None을 반환합니다.
pop(A)는 A라는 키를 가진 값을 반환하고, 기존 딕셔너리에서 삭제시켜줍니다.
update(A)는 A라는 딕셔너리를 기존 딕셔너리에 추가해줍니다.
clear()는 딕셔너리를 비워줍니다.
세트(Set)
세트도 기존과는 살짝 다른 성질을 띄는 자료구조입니다.
세트는 순서가 없으며 값들을 추가, 삭제할 수 있는데요.
주의할 점은 순서가 없기 때문에 index로 접근이 불가능합니다.
특이한 점은 중복해서 저장이 되지 않는다는 것입니다.
마치 하나의 집합처럼 사용할 수 있고, 실제로 집합 연산자를 사용하실 수 있습니다.
# 세트 생성
numbers = {1, 2, 3, 3, 4, 5, 5}
print(numbers) # {1, 2, 3, 4, 5} (중복 제거됨)
# 요소 추가
numbers.add(6)
print(numbers) # {1, 2, 3, 4, 5, 6}
# 요소 삭제
numbers.remove(2)
print(numbers) # {1, 3, 4, 5, 6}
# 집합 연산
A = {1, 2, 3}
B = {3, 4, 5}
print(A | B) # 합집합: {1, 2, 3, 4, 5}
print(A & B) # 교집합: {3}
print(A - B) # 차집합: {1, 2}
간단하게 추가, 삭제가 가능하고, 집합 연산자들을 모두 사용할 수 있죠.
세트에서 사용할 수 있는 연산자들도 살펴볼게요.

새로운 함수들이 많이 등장했네요.
# 세트 생성
my_set = {1, 2, 3, 4, 5}
len(my_set) # 5
3 in my_set # True
10 in my_set # False
my_set.add(6) # {1, 2, 3, 4, 5, 6}
my_set.remove(3) # {1, 2, 4, 5, 6} KeyError 발생 (주의!)
my_set.discard(10) # {1, 2, 4, 5, 6} (변화 없음)
popped_value = my_set.pop() # popped_value = 1 (세트라서 임의의 값이 제거됨)
my_set.clear() # my_set = set()
# 새로운 세트 생성
set1 = {1, 2, 3}
set2 = {3, 4, 5}
# union() : 합집합 (set1 ∪ set2)
set1.union(set2) # {1, 2, 3, 4, 5}
# intersection() : 교집합 (set1 ∩ set2)
set1.intersection(set2) # {3}
# difference() : 차집합 (set1 - set2)
set1.difference(set2) # {1, 2}
set2.difference(set1) # {4, 5}
len(A)의 경우 세트 A의 길이를 측정해줍니다.
in의 경우 마찬가지로 왼쪽의 값이 오른쪽의 세트에 있는지 체크해줍니다.
add(A)의 경우 세트에 값 A를 추가해줍니다.
remove(A)는 세트에 A값이 있을 경우 삭제해주고, 없으면 KeyError를 발생시킵니다.
discard(A)는 세트에 A값이 있을 경우 삭제해주고, 없을 경우 무시합니다.
pop()은 세트의 값을 무작위로 삭제시킵니다.
clear는 세트를 초기화합니다.
B.union(A)은 합집합으로 두 세트 A,B의 합집합을 구해줍니다.
B.intersection(A)는 두 세트 A,B의 교집합을 구해줍니다.
A.difference(B)는 두 세트 A,B의 차집합을 구해줍니다.
정리
지금까지 파이썬의 자료구조형인 리스트, 튜플, 딕셔너리, 세트에 대해 알아봤습니다.
이 자료구조형들은 그럼 언제 쓰는게 적합할까요?
간단하게 아래의 상황속에서 사용할 수 있을 것 같습니다.
| 상황 | 자료구조형 |
| 자료형에 순서가 필요한 경우 | List, Tuple |
| 값의 변경이 필요한 경우 | List |
| 변경하면 안되는 고정값인 경우 | Tuple |
| Key로 데이터를 관리할 경우 | Dictionary |
| 중복을 제거가 필요한 경우 | Set |
앞으로 더 많은 예제에서 다뤄볼 예정이니, 당장 헷갈린다고 해도 너무 걱정마세요!
그럼 다음 포스팅에서 만나요~

'언어 마스터 > 파이썬' 카테고리의 다른 글
| 파이썬 빈도수 계산 모듈 collections.Counter 총정리 (0) | 2025.02.12 |
|---|---|
| 파이썬 기초 강의 2강 변수와 데이터 타입 (6) | 2025.02.09 |
| 파이썬 기초 강의 1강 파이썬이란? (0) | 2025.01.31 |