본문 바로가기

TIL/Python

Python 타입의 동작과 특징

 

Python의 데이터 타입은 프로그래밍에서 매우 중요한 개념입니다. 특히, 데이터 타입이 어떻게 동작하는지 이해하면 코드의 효율성과 안정성을 높일 수 있습니다.
이번 글에서는 mutable(변경 가능)과 immutable(변경 불가능) 타입, 깊은 복사와 얕은 복사, 그리고 Python 문자열이 불변(immutable)인 이유에 대해 알아보겠습니다.

 


Mutable과 Immutable 타입

Mutable vs Immutable

Python의 데이터 타입은 크게 mutable(변경 가능)immutable(변경 불가능)으로 나뉩니다.

 

Immutable 변경 불가능 int, float, bool, str, tuple
Mutable 변경 가능 list, dict, set

Immutable 예제

Immutable 타입은 값을 변경하려고 하면 새로운 객체가 생성됩니다.

x = 10 
print(id(x)) # 메모리 주소 출력

x = x + 5 
print(id(x)) # 값이 변경되면서 새로운 객체가 생성됨

위 코드에서 x의 값을 변경하면 기존 객체를 수정하는 것이 아니라, 새로운 객체가 생성됩니다.

Mutable 예제

Mutable 타입은 객체를 직접 변경할 수 있습니다.

lst = [1, 2, 3] 
print(id(lst)) # 초기 리스트의 메모리 주소 

lst.append(4) 
print(id(lst)) # 동일한 메모리 주소 (객체가 변경됨)

리스트(list)는 append()를 사용해 값을 추가하더라도 메모리 주소가 변하지 않습니다.

 


깊은 복사와 얕은 복사

얕은 복사(Shallow Copy)

Python에서 = 을 사용하면 같은 객체를 참조하는 얕은 복사가 발생합니다.

a = [1, 2, 3] 
b = a # 같은 객체를 참조 

b.append(4) 
print(a) # 결과: [1, 2, 3, 4] → a도 함께 변경됨
 
  • b = a는 새로운 리스트를 만드는 것이 아니라 a의 주소를 b가 공유하는 것입니다.
  • 따라서 b.append(4)를 실행하면 a도 영향을 받습니다.

깊은 복사(Deep Copy)

깊은 복사는 원본 객체와 독립적인 복사본을 생성하는 방식입니다.

import copy 

a = [1, 2, [3, 4]] 
b = copy.deepcopy(a) # 깊은 복사 

b[2].append(5) 
print(a) # 결과: [1, 2, [3, 4]] (원본이 변경되지 않음) 
print(b) # 결과: [1, 2, [3, 4, 5]] (복사본만 변경됨)
  • copy.deepcopy()를 사용하면 내부 객체까지 완전히 새로운 복사본을 생성합니다.
  • 원본과 복사본이 완전히 독립적이므로 한 쪽을 변경해도 다른 쪽에 영향을 미치지 않습니다.

얕은 복사가 문제가 될 수 있는 경우

a = [[1, 2], [3, 4]] 
b = a[:] # 얕은 복사 

b[0].append(5) 
print(a) # 결과: [[1, 2, 5], [3, 4]] (원본도 변경됨)

리스트 안에 리스트가 있는 경우, 얕은 복사는 내부 리스트를 참조하는 형태가 되어 원본까지 변경될 수 있습니다.
따라서 중첩된 리스트나 객체를 복사할 때는 깊은 복사를 고려해야 합니다.


Python 문자열이 불변(Immutable)인 이유

Python의 문자열(str)은 Immutable(불변 객체)입니다. 즉, 문자열의 내용을 변경할 수 없습니다.

문자열이 불변한 이유

  1. 메모리 효율성
    • 문자열이 불변이면 같은 문자열을 여러 곳에서 사용할 때 중복 저장을 피할 수 있음.
    • interning(문자열 캐싱) 기법을 통해 동일한 문자열을 한 번만 저장하여 메모리 절약.
  2. 안전성
    • 여러 곳에서 참조할 때도 값이 변하지 않기 때문에 버그를 예방할 수 있음.
    • 해시 값을 이용하는 dict의 키로 사용할 수 있음.

문자열 변경 시 객체가 새로 생성되는 예제

s = "hello" 
print(id(s)) # 문자열의 메모리 주소 

s = s + " world" 
print(id(s)) # 새로운 문자열이 생성됨 (주소 변경)

기존 s가 변경된 것이 아니라 새로운 문자열 객체가 생성되었음을 알 수 있습니다.

문자열을 수정하려면?

문자열은 불변이므로 직접 수정할 수 없지만, 새로운 문자열을 만들어야 합니다.

s = "Python" 
s = s.replace("P", "J") # 새로운 문자열 생성 
print(s) # "Jython"

리스트는 가변(mutable)

반대로, 리스트는 가변이므로 수정이 가능합니다.

lst = ["P", "y", "t", "h", "o", "n"] 
lst[0] = "J" 
print("".join(lst)) # "Jython"

마무리

이번 글에서는 Python에서 Mutable과 Immutable 타입, 깊은 복사와 얕은 복사, 그리고 문자열이 불변인 이유에 대해 알아보았습니다.

  • Mutable 타입(list, dict, set)은 변경이 가능하고, Immutable 타입(int, str, tuple)은 변경할 수 없습니다.
  • 얕은 복사는 참조를 공유하여 원본을 변경할 위험이 있지만, 깊은 복사는 독립적인 객체를 생성합니다.
  • 문자열이 불변한 이유메모리 효율성과 안전성 때문입니다.

다음 글에서는 타입별 연산자(숫자형, 문자형)소수점 표현 방식을 다루겠습니다.

이 글에서 다룬 내용 외에도 궁금한 점이 있거나, 잘못된 부분이 있다면 댓글로 자유롭게 알려주세요. 여러분의 피드백은 글을 더 발전시키는 데 큰 도움이 됩니다! 😊

'TIL > Python' 카테고리의 다른 글