리스트
0. 리스트의 기본 개념
여러개의 값을 하나의 변수에 순서대로 저장하는 자료형이다.
컨테이너 자료형이며, 데이터 전처리 과정에서 핵심적으로 사용된다.
# 1. 리스트 생성
my_list = [1, 2, 3, 4, 5]
# 2. list()함수 사용
chars = list('hello')
# 3. 리스트의 기본 구조 츨력
print(my_list) # 출력: [1, 2, 3, 4, 5]
print(chars) # 출력: ['h', 'e', 'l', 'l', 'o']
핵심 키워드
• 저장된 값에는 순서(index) 가 있다
• 여러 개의 값을 저장할 수 있다
• 서로 다른 자료형을 함께 저장할 수 있다
• 생성 이후에도 내용을 변경할 수 있다.
0-1. 리스트의 변경 가능성 (Mutability)
리스트는 변경 가능한 객체로서, , 리스트가 한 번 생성된 이후에도 내부 요소를 직접 수정할 수 있다.
이는 뒤에서 설명할 얕은복사, 깊은복사, 메모리 관리와 데이터 처리 방식에서 매우 중요하다.
1. 리스트 인덱싱과 슬라이싱
인덱싱이란 리스트에서 특정 위치의 요소 하나를 선택하는 방법이다.
• 인덱스는 0부터 시작한다
• 음수 인덱스는 뒤에서부터 접근한다
사용 예시
cities = ["Seoul", "Busan", "Incheon"]
print(cities[0]) # Seoul
print(cities[-1]) # Incheon
슬라이싱 = 원하는 부분을 자르는 것.
리스트[start : stop : step]
• start: 슬라이싱을 시작할 인덱스 (포함).
• stop: 슬라이싱을 종료할 인덱스 (미포함).
• step: 요소를 건너뛰는 간격.
사용 예시
cities = ["Seoul", "Busan", "Incheon", "Gwangju", "Daejeon"]
sub = cities[1:4]
print(sub)
# 출력: ['Busan', 'Incheon', 'Gwangju']
2. 리스트의 메소드
파이썬은 리스트를 조작하기 위한 다양한 내장 메소드를 제공한다.
append / insert / extend (요소의 추가)
my_list.append(6)
my_list.insert(2, 10)
my_list.extend([7, 8, 9])
• append - 리스트에 하나의 값(요소) 을 맨 뒤에 추가
• insert - 기존 순서를 유지하면서, 지정한 위치(index) 에 값을 삽입 (이때 기존 값들은 오른쪽으로 한 칸씩 밀린다 )
• extend- 여러 개의 값을 풀어서 추가 → “리스트와 리스트를 이어 붙인다”란 개념으로 접근
remove / pop / clear (요소의 제거)
my_list.remove(3)
popped_value = my_list.pop(5)
my_list.clear()
• remove - 값을 기준으로 첫 번째로 일치하는 요소를 제거
• pop - 지정한 인덱스의 요소를 제거하고 그 요소를 반환한다. 반환 인덱스를 지정하지 않으면 마지막 요소를 제거
• clear - 모든 요소를 제거
index / count ( 요소 검색 및 개수 세기 )
my_list.index(4)
my_list.count(7)
• index - 요소의 인덱스를 반환. 특정 값이 처음 등장하는 위치를 알려준다
• count - 요소의 개수를 반환. 특정 값이 몇 번 등장하는지 세어준다
sort / reverse ( 정렬 )
my_list.sort()
my_list.reverse()
• sort - 리스트의 요소를 오름차순으로 정렬
• reverse - 리스트의 요소 순서를 반대로 뒤집는다
3. 리스트의 연산
리스트는 연산자를 사용할 수 있다.
list1 = [1, 2, 3]
list2 = [4, 5, 6]
result = list1 + list2
print(result) # 출력: [1, 2, 3, 4, 5, 6]
print(list1*2) # 출력: [1, 2, 3, 1, 2, 3]
• + : 리스트 결합
• * : 반복 생성
4, 리스트 컴프리헨션
기존 for문 + 조건문 패턴을 한 줄로 표현해 간결하고 효율적인 방법으로 새로운 리스트를 생성하는 문법 이다.
[표현식 for 변수 in 반복가능객체]
[표현식 for 변수 in 반복가능객체 if 조건]
읽는 순서
- for x in range(...)
- if 조건
- 맨 앞의 표현식
# 일반적인 for문
result = []
for x in range(1, 6):
result.append(x)
# 리스트 컴프리헨션
result = [x for x in range(1, 6)]

실행 순서 (Line by Line)
| 1. range(1, 6) 생성 2. 첫 값 x = 1 3. 표현식 x 실행 → 1 4. 리스트에 추가 5. 반복 종료까지 반복 |
5. 리스트의 반복문 활용
리스트의 각 요소에 접근하거나 처리하기 위해 반복문을 사용할 수 있다.
fruits = ['apple', 'banana', 'cherry']
for fruit in fruits:
print(fruit, end = ' ')
# 출력: apple banana cherry
인덱스와 함께 반복할수도 있다.
# enumerate : 인덱스와 값을 함께 불러올 수 있습니다.
for index, value in enumerate(fruits):
print(f'인덱스 {index}: {value}')
6. 중첩문
리스트 안에 또 하나의 리스트를 넣을수도 있다
matrix = [
[1, 2],
[3, 4],
[5, 6]
]
for row in matrix:
for value in row:
print(value) # 출력: 1 2 3 4 5 6
개념적으로 보면
바깥 for문 → “행 단위 접근”
안쪽 for문 → “해당 행의 요소 접근”
리스트 컴프리헨션에서 중첩이 등장할 때도 이 순서가 그대로 유지된다.
⭐ 중첩 리스트는 항상 밖에서부터 안쪽을 천천히 까보면서 들어가야 한다. ⭐
7. 리스트의 얕은 복사, 깊은 복사
파이썬에서의 리스트는 값이 아닌 '객체' 즉, 메모리에 따로 저장되는 요소라 봐도 무방하다.
이때의 변수는 리스트가 저장된 위치를 가리키는 이름표라 생각하면 편하다.
| a = [1, 2, 3] → a 안에 [1, 2, 3]이 들어있다 ❌ a는 [1, 2, 3]이 “있는 위치를 가리킨다” ⭕ 그림으로 보면.... 메모리 어딘가: [1, 2, 3] ← 실제 리스트 a ─────────▶ [1, 2, 3] |
설명하기전 짚고 넘어가기
a = [1, 2, 3]
b = a
해당 코드는 다음과 같이 표현된다.
a ─────▶ [1, 2, 3]
b ─────▶ [1, 2, 3]
리스트는 1개이지만, 이름표가 a와 b 이다.
만약 여기서 append를 해 b를 바꿔보자
b.append(4)
print(a)
# 출력 [1, 2, 3, 4]
??
분명 b에 append를 사용해서 바꾸었는데 a도 바뀌였다.
왜 a도 바뀐걸까?
[1, 2, 3, 4]
이유는 a와 b모두 같은 리스트를 가르키고 있기 때문이다.
7-1. 얕은 복사(Shallow Copy)란?
겉에 있는 리스트만 새로 만들고 안에 들어 있는 리스트는 같이 쓰는 복사
• 리스트 껍데기는 새 것
• 안에 들어 있는 객체들은 공유
original = [1, 2, [3, 4]]
shallow = original[:]
메모리의 관점
original ──▶ [1, 2, ──▶ [3, 4]]
shallow ──▶ [1, 2, ──▶ [3, 4]]
겉리스트는 2개지만, 안의 리스트는 1개다.
즉...
shallow[2][0] = 'a'
print(original)
# [1, 2, ['a', 4]]
print(shallow)
# [1, 2, ['a', 4]]
겉의 리스트는 다른 리스트를 사용하지만, 속은 같은 리스트를 사용하기 때문에 변한것이다.
즉, “껍데기만 복사하고, 안에 든 객체는 같이 쓴다” 라는 의미다.
어떨때 발생하나?
• 슬라이싱 [:]
• list()
• copy.copy()
• list.copy()
❗ 주의사항 ❗
• 숫자, 문자열은 안 바뀌는 값
• 안에 또 리스트가 없음
• 1차원 리스트 → 얕은 복사 OK
7-2. 깊은 복사(Deep Copy) 란?
바깥 리스트, 그 안의 모든 하위 객체를 전부 새로 복사한다.
원본과 복사본이 어느 수준에서도 객체를 공유하지 않는다
즉, 객체 구조 전체를 새로 만드는것이라 볼수 있다.
import copy
original = [1, 2, [3, 4]]
deep = copy.deepcopy(original)
만약 deep의 값을 변경하면?
deep[2][0] = 'a'
print(original)
# [1, 2, [3, 4]]
print(deep)
# [1, 2, ['a', 4]]
겉과 속 모두 다른 리스트를 가리키고 있기때문에 개별적이라 볼수 있다.
7-3. 표로 보기
| 구분 | 얕은 복사 | 깊은 복사 |
| 바깥 객체 | 새로 생성 | 새로 생성 |
| 내부 객체 | 공유 | 전부 새로 생성 |
| 독립성 | 부분적 | 완전 |
| 중첩 리스트 | 위험 | 안전 |
7-4 어렵다면 이렇게 생각하기
안에 리스트가 있나?
없다 → 얕은 복사 OK
있다 → 깊은 복사 필요
8. 리스트와 메모리 관리
파이썬에서 변수는 “값을 담는 상자”가 아니라 객체를 가리키는 이름표이다
a = [1, 2, 3]
b = a
• 리스트 객체는 메모리에 하나
• a, b는 같은 주소를 참조
만약 리스트가 변경되면...
b.append(4)
• 리스트 객체 자체가 변경됨
• 그 객체를 참조하는 모든 변수가 영향을 받음
얕은 복사
- 바깥 리스트 주소는 다름
- 내부 리스트 주소는 같음
깊은 복사
- 모든 객체가 서로 다른 주소
- 완전 독립
9. 리스트의 실용 예제
중복 제거
리스트에는 같은 값이 여러 번 들어갈 수 있다. 만약 중복을 제거한 값이 필요한 경우... set을 사용한다.
수도코드로 보기
| 숫자가 여러 개 들어 있는 리스트를 준비한다 리스트를 set으로 변환하여 중복을 제거한다 다시 리스트로 변환한다 결과를 출력한다 |
numbers = [1, 2, 2, 3, 4, 4, 5]
unique_numbers = list(set(numbers))
print(unique_numbers)
실행 순서 (Line by Line)
| 1. numbers 리스트 생성 # [1, 2, 2, 3, 4, 4, 5] 2. set(numbers) 실행 # {(1, 2, 3, 4, 5) 3. 중복된 2,4는 하나만 남는다. (순서 보장 x) 4. list(...) 실행 # [1, 2, 3, 4, 5] |
컴프리헨션을 사용한 조건부 리스트
1부터 20까지 숫자 중 3의 배수만 리스트로 만들기
수도코드로 보기
| 1부터 20까지 숫자를 하나씩 확인한다 해당 숫자가 3으로 나누어 떨어지면 리스트에 추가한다 |
multiples_of_three = [x for x in range(1, 21) if x % 3 == 0]
print(multiples_of_three)
#출력: [3, 6, 9, 12, 15, 18]
실행 순서 (Line by Line)
| 1. range(1, 21) 생성 2. 값 x의 몫이 0이면 참(값을 반환), 0아 아니면 거짓 (다음 x 값으로) 3. 리스트 출력 |
2차원 리스트에서의 특정 조건의 요소 찾기
수도코드로 보기
| 각 행(row)을 하나씩 가져온다 행 안의 각 요소(item)를 하나씩 확인한다 item이 30보다 크면 결과 리스트에 추가한다 |
matrix = [
[5, 10, 15],
[20, 25, 30],
[35, 40, 45]
]
result = [item for row in matrix for item in row if item > 30]
print(result)
# 출력 [35, 40, 45]
실행 순서 (Line by Line)
| 1. 첫 번째 행 검사 [5, 10, 15] 2. 두번째 행 검사 [20. 25. 30] 3 세 번째 행 검사 [35, 40, 45] (모두 30을 초과했기 때문에 리스트에 반환) 4. 출력 |
10. 리스트 학습한 내용
- 리스트의 기본 개념과 변경 가능성
- 인덱싱과 슬라이싱의 동작 원리
- 리스트 주요 메소드의 내부 동작 방식
- 리스트 연산과 반복문의 결합
- 리스트 컴프리헨션의 구조적 의미
- 중첩 리스트와 메모리 참조 개념
- 데이터 전처리에 활용되는 실용 패턴
튜플
0. 튜플의 기본 개념
여러 개의 값을 하나로 묶어 저장하는 자료형이다.
리스트와 매우 유사하지만, 가장 큰 차이점은 값을 변경할 수 없다는 점이다.
• 순서가 존재
• 요소의 추가, 삭제, 변경이 불가능
• 여러 데이터를 담을수 있음
• 대괄호 [ ]를 사용하여 리스트 생성
0-1. 튜플의 불변성
튜플은 불변(immutable) 자료형이다.
한 번 생성된 튜플은 요소의 추가, 삭제, 수정이 불가능하다.
1. 튜플의 생성법
기본 생성
t1 = (1, 2, 3)
t2 = 1, 2, 3
요소가 하나인 튜플
t3 = (1,) # 쉼표 필수
t4 = (1) # 튜플 아님, 정수
튜플 패킹
# () 없이 생성 (튜플패킹)
my_tuple = 1, 2, 3
print(my_tuple) # 출력: (1, 2, 3)
print(type(my_tuple)) # 출력: <class 'tuple'>
함수를 이용한 생성
# tuple()함수를 사용해 생성
my_list = [1, 2, 3]
my_tuple = tuple(my_list) # 리스트를 튜플로 변환
print(my_tuple) # 출력: (1, 2, 3)
2. 튜플 인덱싱 & 슬라이싱
튜플도 순서가 있는 자료형이므로 인덱싱과 슬라이싱이 가능하나, 다른점은 ❗수정은 불가능❗
fruits = ('apple', 'banana', 'cherry', 'date')
print(fruits[0]) # 출력: apple
print(fruits[2]) # 출력: cherry
print(fruits[-1]) # 출력: date (마지막 요소)
print(fruits[-2]) # 출력: cherry
튜플 슬라이싱
numbers = (0, 1, 2, 3, 4, 5, 6)
print(numbers[2:5]) # 출력: (2, 3, 4)
print(numbers[:3]) # 출력: (0, 1, 2)
print(numbers[4:]) # 출력: (4, 5, 6)
print(numbers[::2]) # 출력: (0, 2, 4, 6)
print(numbers[::-1]) # 출력: (6, 5, 4, 3, 2, 1, 0)
3. 튜플 메소드(Tuple Methods)
count() - 특정 요소의 개수를 반환. 특정 값이 몇 번 등장했는지
numbers = (1, 2, 2, 3, 3, 3)
print(numbers.count(2)) # 출력: 2
print(numbers.count(3)) # 출력: 3
index() - 첫 번째로 일치하는 요소의 인덱스를 반환. 특정 값이 처음 등장한 위치 확인
fruits = ('apple', 'banana', 'cherry')
print(fruits.index('banana')) # 출력: 1
4. 튜플과 리스트의 차이점
| 구분 | 리스트 | 튜플 |
| 변경 가능 | O | X (불변성 때문) |
| 추가/삭제 | 가능 | X (불변성 때문) |
| 용도 | 데이터 조작이 필요한 경우 | 변경이 불필요한 테이터 key |
| 성격 | 작업용 | 고정데이터, 보관용 |
| 비유 | 메모장 | 인쇄된 문서 |
5. 튜플의 활용
딕셔너리의 키로 활용
딕셔너리의 키는 변경 불가능한 자료형만 가능하므로 튜플은 키로 사용할 수 있다.
my_dict = { (1, 2): "Point A", (3, 4): "Point B" }
print(my_dict[(1, 2)]) # 출력: Point A
함수의 복수 반환값
수도코드로 보기
| 함수에서 두 값을 한 번에 반환한다 |
def calc(a, b):
return a + b, a - b
result = calc(10, 3)
# (13, 7)
변수의 패킹과 언패킹
패킹: 여러개의 값을 하나의 튜플로 묶는것을 의미
packed_tuple = 1, 2, 3
print(packed_tuple) # 출력: (1, 2, 3)
언패킹: 튜플의 요소를 여러 개의 변수에 할당하는 것을 의미
a, b, c = packed_tuple
print(a) # 출력: 1
print(b) # 출력: 2
print(c) # 출력: 3
6. 중첩 튜플(Nested Tuples)
튜플 안에 튜플을 요소로 가질 수 있습니다.
t = ((1, 2), (3, 4))
# 접근법
print(t[0][1])
#출력: 2
7. 튜플의 반복문 활용
튜플의 각 요소에 접근하거나 처리하기 위해 반복문을 사용할 수 있다.
fruits = ('apple', 'banana', 'cherry')
for fruit in fruits:
print(fruit)
apple
banana
cherry
인덱스와 함께 반복
for index, value in enumerate(fruits):
print(f'인덱스 {index}: {value}')
인덱스 0: apple
인덱스 1: banana
인덱스 2: cherry
8. 튜플의 비교와 정렬
튜플은 요소별로 비교할 수 있으며, 정렬된 시퀀스를 필요로 하는 경우에 유용하다.
# 튜플끼리의 비교
tuple1 = (1, 2, 3)
tuple2 = (1, 2, 4)
print(tuple1 < tuple2) # 출력: True
튜플 안에 존재하는 리스트를 정렬 할수도 있다.
students = [('John', 'A', 15), ('Jane', 'B', 12), ('Dave', 'A', 10)]
# 나이를 기준으로 정렬
students_sorted = sorted(students, key=lambda student: student[2])
print(students_sorted)
# 출력: [('Dave', 'A', 10), ('Jane', 'B', 12), ('John', 'A', 15)]
9. 실용예제
두 변수의 값 교환
a = 10
b = 20
a, b = b, a # 값 교환
print(a) # 출력: 20
print(b) # 출력: 10
리스트와 상호 변환
my_tuple = (1, 2, 3)
my_list = list(my_tuple)
print(my_list) # 출력: [1, 2, 3]
my_new_tuple = tuple(my_list)
print(my_new_tuple) # 출력: (1, 2, 3)
여러 변수에 동일한 값 할당
x = y = z = 0
print(x, y, z) # 출력: 0 0 0
10. 튜플 학습한 내용
- 튜플은 변경할 수 없는 자료형이다
- 리스트와 문법은 유사하지만 용도가 다르다
- 안전하게 데이터를 보호해야 할 때 튜플을 사용한다
- 함수 반환값, 딕셔너리 키, 값 교환에 자주 활용된다
딕셔너리
값을 위치(index)가 아닌 키(key)와 값(value)을 한 쌍으로 저장하는 자료형
리스트나 튜플과 달리, 순서가 아니라 키를 통해 값에 접근한다.
키(key)과 값(value)의 쌍을 저정한다.
값(value)은 뭐든 될 수 있다
•숫자
•문자열
•리스트
•튜플
•딕셔너리 조차 가능
# 빈 딕셔너리 생성
empty_dict = {}
# 키-값 쌍을 가진 딕셔너리
person = {
'name': 'Alice',
'age': 25,
'city': 'New York'
}
print(empty_dict) # 출력: {}
print(person) # 출력: {'name': 'Alice', 'age': 25, 'city': 'New York'}
⭐ 순서가 목적이 아니다. 딕셔너리는 “몇 번째냐”가 아닌 “무엇이냐”가 중요하다 ⭐
1. 딕셔너리 생성 방법
중괄호 {} 사용
# 기본적인 딕셔너리 생성
student = {
'id': 12345,
'name': 'John Doe',
'grade': 'A'
}
dict()를 사용
# 키워드 인자를 사용한 생성
car = dict(brand='Ford', model='Mustang', year=1964)
print(car) # 출력: {'brand': 'Ford', 'model': 'Mustang', 'year': 1964}
# 리스트나 튜플의 리스트를 사용한 생성
items = [('apple', 2), ('banana', 3)]
fruit_dict = dict(items)
print(fruit_dict) # 출력: {'apple': 2, 'banana': 3}
2. 딕셔너리 요소 접근 및 변경
요소의 접근
수도코드로 보기
| 키를 이용해 해당 값을 가져온다 |
person = {'name': 'Alice', 'age': 25, 'city': 'New York'}
# 키를 사용하여 값에 접근
print(person["name"])
# 출력: Alice
# `get()` 메서드를 사용하여 값에 접근 (키가 없을 때 기본값 설정 가능)
print(person.get('city')) # 출력: New York
값 변경
수도코드로 보기
| 기존 키에 새로운 값을 할당한다 |
person["age"] = 26
요소 추가&삭제
# 값의 추가
person["job"] = "Data Analyst"
# `del` 키워드를 사용하여 요소 삭제
del person['city']
print(person) # 출력: {'name': 'Alice', 'age': 26, 'country': 'USA'}
# `pop()` 메서드를 사용하여 요소 삭제 및 값 반환
age = person.pop('age')
print(age) # 출력: 26
print(person) # 출력: {'name': 'Alice', 'country': 'USA'}
# 모든 요소 삭제
person.clear()
print(person) # 출력: {}
3. 딕셔너리 메소드
keys()
모든 키를 dict_keys 객체로 반환 ( 컬럼 목록 확인 느낌 )
person = {'name': 'Alice', 'age': 25, 'city': 'New York'}
keys = person.keys()
print(keys) # 출력: dict_keys(['name', 'age', 'city'])
values()
모든 값을 dict_values 객체로 반환 ( 실제 데이터들만 모아서 보기 )
person = {'name': 'Alice', 'age': 25, 'city': 'New York'}
keys = person.keys()
print(keys) # 출력: dict_keys(['name', 'age', 'city'])
items()
딕셔너리의 모든 키-값 쌍을 튜플로 반환
items = person.items()
print(items) # 출력: dict_items([('name', 'Alice'), ('age', 25), ('city', 'New York')])
4. 딕셔너리의 반복문 활용
4-1. 키를 통한 기본 반복
for key in person:
print(key, person[key])
4-2. keys() 메소드 활용
for key in person.keys():
print(key)
4-3. values() 메소드 활용
for value in person.values():
print(value)
4-4. items() 메소드 활용
for key, value in person.items():
print(key, value)
5. 딕셔너리의 컴프리헨션
반복문과 조건을 사용해 딕셔너리를 한 줄로 생성하는 문법
squares = {x: x**2 for x in range(1, 6)}
6. 딕셔너리와 관련된 함수들
6-1. len()
딕셔너리의 키-값 쌍의 개수를 반환
person = {'name': 'Alice', 'age': 26, 'city': 'New York', 'country': 'USA'}
print(len(person)) # 출력: 4
6-2. in 연산자
딕셔너리에 특정 키가 존재하는지 확인
print('name' in person) # 출력: True
print('email' in person) # 출력: False
6-3. del 키워드
딕셔너리 자체를 삭제하거나 모든 요소를 삭제
del person['country'] # 특정 키-값 쌍 삭제
del person # 딕셔너리 전체 삭제
7. 중첩 딕셔너리
딕셔너리 안에 또 다른 딕셔너리를 저장할 수 있다.
students = {
"Alice": {"math": 90, "eng": 85},
"Bob": {"math": 75, "eng": 80}
}
print(students["Alice"]["math"])
# 출력: 90
8.딕셔너리의 응용
키로 사용할 수 없는 자료형
# 다음 코드는 오류를 발생시킵니다.
my_dict = { [1, 2, 3]: 'Numbers' } # TypeError: unhashable type: 'list'
람다(lambda) 함수란?
이름 없는 간단한 함수를 의미한다.
# 같은 의미
square = lambda x: x * x # 람다
def square(x): return x * x # def
add = lambda a, b: a + b # 람다
def add(a, b): return a + b # def
기능적 관점에서 보면 두 함수 모두 입력값 받아 return으로 값을 반환한다.
람다를 쓰는 이유는...
잠깐 쓰고 버릴 함수로 쓰기 위해서이다.
9. 딕셔너리와 JSON 데이터
JSON은 키-값 구조의 데이터 포맷이고, 파이썬 딕셔너리와 구조가 매우 유사하다.
import json
person = {'name': 'Alice', 'age': 25, 'city': 'New York'}
# 딕셔너리를 JSON 문자열로 변환
json_str = json.dumps(person)
print(json_str)
# 출력: {"name": "Alice", "age": 25, "city": "New York"}
(오픈/공공 데이터가 JSON 형태인 경우가 많아, 파이썬 딕셔너리 형태로 변환하여 처리하는 경우 다수)
10. 딕셔너리 학습한 내용
- 딕셔너리는 키-값 구조의 자료형이다
- 키를 통해 빠르게 값에 접근할 수 있다
- 반복문과 컴프리헨션을 통해 효율적으로 처리할 수 있다
- 중첩 구조를 통해 복잡한 데이터 표현이 가능하다
- JSON 데이터 처리의 기본이 되는 자료형이다
[보충] Immutable / Mutable 개념 정리
1. 객체(Object)란 무엇인가?
정수, 실수, 문자열, 리스트, 튜플, 딕셔너리, 함수까지 모두 메모리 공간에 저장된것을 객체라 부른다.
즉, 값(value)과 기능(Methods)을 함께 가진 데이터 덩어리를 의미한다.
객체는 다음 두 가지를 반드시 가집니다.
• 값(Value)
• 주소(Address, 메모리 위치)
예를 들어
a = 10
이 문장은 다음 의미를 가진다.
• 메모리에 10이라는 값이 저장됨
• 변수 a는 그 값이 저장된 주소를 가리킴
여기서 포인트는 변수는 값을 직접 담고 있는 것이 아니라, 객체를 가리키고 있다는 점이다.
2. Immutable / Mutable의 핵심 차이
| 구분 | 뜻 | 정리 |
| Immutable | 바꿀 수 없음 | 객체 자체를 수정할 수 없음 |
| Mutable | 바꿀 수 있음 | 객체 자체를 수정할 수 있음 |
중요한 포인트는 “변수를 바꾼다”와 “객체가 바뀐다”는 전혀 다른 개념
같은 객체를 유지한 채 내용만 바꿀 수 있는가?
3. Immutable 객체 (변경 불가능)
대표적인 immutable 자료형은 다음과 같다.
- int
- float
- bool
- str
- tuple
a = 10
a = a + 1
겉보기에는 a가 11로 바뀐 것처럼 보이지만 실제로는 다음 순서로 동작한다.
| 10이라는 객체 생성 a가 10을 가리킴 11이라는 새로운 객체 생성 a가 11을 가리키도록 변경 |
즉, 10 객체는 그대로 존재
a가 가리키는 대상만 바뀌였다.
s = "hello"
s[0] = "H" # 에러 발생
# 해결책
s = "H" + s[1:]
이유:
문자열은 immutable
문자열 내부의 문자 하나도 직접 수정 불가
때문에 새 문자열 생성 해야 한다.
4. Mutable 객체 (변경 가능)
대표적인 mutable 자료형은 다음과 같다.
- list
- dict
- set
lst = [1, 2, 3]
lst[0] = 100
print(lst) #출력: [100, 2, 3]
코드 동작 순서
- [1, 2, 3] 리스트 객체 생성
- lst가 해당 리스트 객체를 가리킴
- 리스트 내부 값 변경
- 객체 주소는 그대로 유지
즉, 객체는 그대로이며 내용만 변경된것이다.
d = {"a": 1}
d["a"] = 100
print(d) #출력: {'a': 100}
딕셔너리도 mutable이므로 내부 값 변경이 가능하다.
5. 헷갈리기 쉬운 포인트
포인트 1: 변수의 변경 ≠ 객체의 변경
a = 10
b = a
a = 20
- a와 b는 처음에 같은 객체(10)를 가리킴
- a = 20은 새 객체를 가리키는 것
- b는 여전히 10을 가리킴
포인트 2: mutable 객체는 참조가 공유됨
a = [1, 2, 3]
b = a
b.append(4)
# 결과
a → [1, 2, 3, 4]
b → [1, 2, 3, 4]
- a와 b가 같은 리스트 객체를 공유
- 리스트는 mutable
6. 표로 정리해서 보기
| 구분 | Immutable | Mutable |
| 객체 수정 | 불가능 | 가능 |
| 객체 재사용 | 불가능 | 가능 |
| 변경 방식 | 새 객체 생성 | 기존 객체 수정 |
| 대표 자료형 | int, float, str, tuple | list, dict, set |
| 비유 | 잉크로 쓴 종이 | 연필로 쓴 노트 |
'B.Review > 파이썬 라이브 세션' 카테고리의 다른 글
| [Python Study] 파이썬 5일차~문푸날 (1) | 2026.01.15 |
|---|---|
| [Python Study] 파이썬 4일차~문푸날 (0) | 2026.01.13 |
| [Python Study] 파이썬 2일차~문푸날 (0) | 2026.01.08 |
| [Python Study] 라이브세션 1회차~문푸날 (0) | 2026.01.06 |
