[Python] 객체의 종류 및 copy 정리

JinUk Lee·2024년 4월 11일

python 개념 공부

목록 보기
7/14

객체의 종류

파이썬에서 객체는 두 종류로 구분할 수 있다

mutable : 단어 뜻 그대로 변형할수 있는 객체 (변경 가능한 객체) - list, set, dict

immutable : 변형할 수 없는 객체 (변경 불가능한 객체) - int, float, tuple, str, bool

immutable

위의 내용을 보고나면 정수인 변수의 값을 왜 못바꾼다는거야? 라고 할 수 있다.

아래의 예시를 보자.


a = 5
b = 5

print(a is b) # True

여기서 a = 5 는 변수 a에 5를 넣으라고 해석하는 것이 아니고, 5라는 객체가 이미 존재하는데 변수 a가 이 객체를 가르킨다고 이해해야한다.

그렇기 때문에 변형할 수 없다고 하는 것이다.

만약 a에 1을 더해서 6을 만들었다면 그건 a가 가르키는 객체가 5에서 6으로 바뀐거지 5라는 객체가 변한것은 아니기 때문이다.

파이썬에서는 이러한 기법을 Object Interning 라고 하며, 기본적으로는 아래와 같은 범위가 존재한다.

  • -5 ~ 256
  • [a-zA-Z0-9]로 구성된 문자열

그러나 우리가 실제로 코드를 구현해보면


a = 10000
b = 10000

print(a is b) # True

256을 훨씬 넘는 범위에서도 a b의 참조 객체가 같은 값을 가지는데, 이는 각 파이썬 환경마다 interning 의 범위가 다르기 때문이며 vscode나 pycharm에선 이 범위가 상당히 크다.

mutable

반면, mutable 객체인 list를 보자

a = [1,2,3,4]
b = [1,2,3,4]

print(id(a),id(b))

a.append(5)

print(id(a),id(b))

같은 값을 가지는 a b 객체의 주소값이 다른 것을 알 수 있다.

그리고 a의 값을 바꾼다고 주소값이 바뀌지 않는다.

즉, a 객체의 값 자체를 변경했기 때문에 mutable로 부르는 것이다.

파이썬의 copy

위에서 설명한 객체의 종류를 알아야 하는 이유가 파이썬의 copy를 이해하기 위함이다.

파이썬에서는 얕은 복사, 깊은 복사라는 개념이 있다.

얕은 복사 : 변수의 주소값을 복사
깊은 복사 : 변수의 값을 복사

흔히 파이썬을 배울때 아래와 비슷한 예시로 간단하게나마 배우고 가는 개념이다.

a1 = [1,2,3,4]
a2 = a1

a2.append(5)
print(a1) # [1,2,3,4,5]

대입연산자 = 는 얕은 복사를 하기때문에 a2의 값을 변경하면 a1도 영향을 받는 것을 알 수 있다.

그런데, 위에서 객체의 값을 변경한다는 행위가 mutable, immutable 에 따라 어떻게 다른지 학습했다.

해당 내용으로 알 수 있는 것은 immutable 객체는 복사를 어떻게 하든 크게 중요하지 않다는 것이다.

위에서 예시로 나온 list를 보면 a1, a2의 참조값이 같기 때문에 a1의 값을 변경하면 a2도 영향을 받는것이 얕은 복사 개념인데, immutable 객체는 a1의 값을 변경하면 주소값이 달라져 a2와의 연결이 끊어지기 때문이다.

그렇기 때문에 얕은 복사, 깊은 복사는 mutable 객체에서만 학습하면 된다.

얕은 복사

얕은 복사를 하는 방법은 4가지가 있다.

  • = 연산자
  • copy() 메서드
  • [:] 슬라이싱
  • copy 모듈의 copy 함수

주의할 점은알고리즘 문제를 풀때 [:] 슬라이싱, copy같은 경우 깊은 복사처럼 사용하는 경우도 종종 있다.

그런데 얕은 복사로 분류 되는 이유는 mutable 객체 내부에 다른 mutable 객체가 존재할 때 주소값을 복사하기 때문이다.


a1=[1,2,3,[4,5,6]]
a2 = a1[:]

a1.append(7)
print(a2) # [1,2,3,[4,5,6]]

a1[3].append(7)

print(a2) # [1,2,3,[4,5,6,7]]

a1의 값을 변경시켰을때 a2는 그대로라서 깊은 복사라고 생각할 수 있지만, a1 내부의 리스트의 값을 변경시켰을땐 a2도 영향을 받기 때문에 얕은 복사이다.

한마디로 깊은 복사처럼 보이지만, 내부에 다른 mutable 객체가 존재할 경우 그 객체의 참조값이 변하지 않는지 판단하는 것이 중요하다.

깊은 복사

깊은 복사를 하는 방법은 copy 모듈의 deepcopy 함수를 사용하는 것이다.

깊은 복사는 객체의 값 자체를 복사해서 새로운 객체를 생성한다.

from copy import deepcopy
a1=[1,2,3,[4,5,6]]
a2 = deepcopy(a1)

a1.append(7)
print(a2) # [1,2,3,[4,5,6]]

a1[3].append(7)
print(a2) # [1,2,3,[4,5,6]]

같은 예시에서 깊은 복사를 하면 a1의 값을 아무리 변경해도 a2에 영향이 가지 않는다.

profile
개발자 지망생

0개의 댓글