상세 컨텐츠

본문 제목

가변객체(mutable)와 불변객체(immutable) / 파이썬

언어/Python

by moonionn 2021. 2. 19. 22:37

본문

저번 글에서 객체와 객체지향 프로그래밍의 성격을 간단히 알아보았는데요,

파이썬 또한 모든걸 객체로 관리하기 때문에 객체지향을 지원하는 언어라고 할 수 있습니다.

print(isinstance('this is string', str))
print(isinstance(['this','is','list'], list))
print(isinstance(('this','is','tuple'),tuple))

# True
# True
# True

 

 

객체에는 세 가지 특징이 있습니다.

 

value type identity
메모리에 저장된 값
int, str, dict 등등
객체의 데이터 타입
일종의 객체 생성자

각 객체가 가진 고유한 ID
일종의 메모리 주소
  type() 로 확인 가능
id()
로 확인 가능
a is b 로 일치불일치 여부 확인 가능

 

 

 

그리고 그 객체들은 생성자(클래스)에 따라

크게 가변객체(mutable)불변객체(immutable)로 나뉩니다.

 

가변객체(mutable)

불변객체(immutable)


list, dict, set, 등등...

str, int, float, tuple, 등등...

 

 

 

가변객체와 불변객체

불변객체

불변객체는 이름 그대로 값을 바꿀 수 없는 객체입니다.

그렇다면 이게 무슨 뜻이냐?

string type으로 예시를 보겠습니다.

x = 'test1'
print(x)

x += ' test2'
print(x)

# test1
# test1 test2

'test1' value를 가진 x의 value를 'test1 test2'로 바꾼 결과입니다.

엥? 멀쩡히 잘만 바뀌는데? 라는 생각이 들지만,

내부적으로 들여다보면 사실 'test1'은 한번도 바뀐 적이 없습니다.

 

x = 'test1'
print(id(x))

x += 'test2'
print(id(x))

# 140450185151280
# 140450185152880

id()는 해당 값이 저장되어 있는 일종의 메모리 위치를 나타냅니다. <- (identity)

만약 'test1'의 value가 변경된 것이라면, 메모리 위치는 동일해야겠죠?

 

하지만 x에 새로운 value'test2'를 부여하면서 메모리 위치가 바뀐 걸 볼 수 있습니다. <- (identity 변경)

따라서 기존의 'test1'이 변경된 것이 아니라, 새로운 object를 생성한 것입니다.

(기존에 존재했던 value 'test1'은 메모리에서 제거됩니다.)

 

x = 1
print(id(x))

x += 1
print(id(x))

# 4318210752
# 4318210784

int type의 연산결과도 마찬가지입니다.

기존의 메모리 주소 속 value가 바뀌는 게 아니라 새로운 object를 생산하죠.

 

x = 'test1'
x[0] = 'tt'

# TypeError: 'str' object does not support item assignment

y = (1,2)
y[0] = 0

# TypeError: 'tuple' object does not support item assignment

따라서 불변객체는 이미 메모리 위에 있는 value를 변경할 수 없습니다.

 

 

불변객체의 copy

x = 'test'
y = x

print(x is y)
# True

x = x + ' modified'

print(x is y)
# False

print(x)
print(y)

# test modified
# test
  • 'test' value를 가진 객체가 생성되어 메모리에 올라갔습니다.
  • 해당 메모리 위치를 y도 지목하도록 합니다.
  • (x is y = True)
  • 그러던 중 x에게 'test' + ' modified' 라는 새로운 value를 부여합니다.
  • string은 불변객체이므로 기존의 것을 변경하지 않고 새로운 object를 생성합니다.
  • 그리고 해당 object는 새로 만들어졌으니, 새로운 메모리 주소에 배정됩니다.
  • (x is y = False)

이로 미루어보아, 불변객체에서 위 두번째줄처럼 y = x가 실행되면

y는 x가 가리키는 메모리의 위치와 그 값을 직접적으로 가리킴을 알 수 있습니다.

 


가변객체

가변객체는 불변객체와 비교해 어떤 식으로 차이가 나는지 보도록 하겠습니다.

대표적인 가변객체 list 예시를 들고와봤습니다.

x = [1, 2, 3]
print(id(x))

x += [4, 5]
print(id(x))

# 140325471720640
# 140325471720640

[1, 2, 3]의 value를 변경했는데, 메모리 위치는 변경되지 않았습니다.

이렇게 가변객체는, 이미 그 value가 메모리에 저장되었다 하더라도 그 내용을 수정할 수 있습니다.

 

x = [1, 2, 3]
print(id(x))

x[0] = 0
print(id(x))

y = {'a' : 1, 'b' : 2}
print(id(y))

y['a'] = 0
print(id(y))

print(x)
print(y)

# 140459840431680
# 140459840431680
# 140459840385792
# 140459840385792
# [0, 2, 3]
# {'a': 0, 'b': 2}

가변객체는 item assignment도 지원합니다.

 

 

가변객체의 copy

x = [1, 2, 3]
y = x

print(x is y)
# True

x += [4, 5]

print(x is y)
# True

print(x)
print(y)

#[1, 2, 3, 4, 5]
#[1, 2, 3, 4, 5]

x[1, 2, 3] 이라는 object 값을 가리키도록 했습니다.

yx를 복사합니다.

헌데 x의 값을 변경했다고 y의 값도 변경되었습니다.

 

이로 미루어보아 가변객체에서의 copy는 메모리 주소와 그 값을 직접 point 하는 것이 아니라,

포인터만 복사함을 알 수 있습니다. (shallow copy)

 

 

(+ deepcopy)

코드를 짜다보면 이런 가변객체를 복사하여 작업하다가

참조 객체까지 변경되어 불편함을 겪을 수 있습니다.

이를 방지하기 위해서는 deepcopy 기능을 써야합니다.

from copy import deepcopy

x = [1, 2, 3]
y = deepcopy(x)

print(x)
print(y)

print(id(x))
print(id(y))

# [1, 2, 3]
# [1, 2, 3]
# 140532955555392
# 140532955557696

테스트 결과 x와 y의 주소값이 다름을 확인할 수 있습니다.

 

 

불변, 가변, 왜 중요한가?

다시 코드를 봅시다.

x = (1,2)
y = (3,4)

print(id(x))
# 140511069579008

x += y

print(id(x))
# 140511069672288

불변객체를 통해 위와 같은 연산을 거치면

새로운 object가 생성되고, 새로운 메모리 공간을 할당해주어야 합니다.

그렇기 때문에 메모리 누수 발생 가능성이 있으며

매번 메모리의 빈 공간을 찾아야하는 이유 등 때문에 비싼 연산을 요구합니다.

 

따라서 프로그램이 커지고, 코드가 복잡해질 수록 성능을 저하시킬 수 있으니

어떤 객체를 선택해서 사용할지 신중히 고민해볼 필요가 있습니다.

 

하지만 불변객체는 그 값이 변하지 않는다는 점 때문에 신뢰도가 높습니다.

고로 상황에 따라 적절한 데이터를 골라 쓸 수 있도록 해야겠습니다.

 

 

 

참고

towardsdatascience.com/https-towardsdatascience-com-python-basics-mutable-vs-immutable-objects-829a0cb1530a

 

Python Basics: Mutable vs Immutable Objects

After reading this blog post you’ll know:

towardsdatascience.com

ichi.pro/ko/python-ui-byeongyeong-ganeung-mich-byeongyeong-bulganeunghan-gaegche-18971482174035

 

Python의 변경 가능 및 변경 불가능한 객체

파이썬에서는 모든 것이 객체입니다. 이것이 의미하는 바를 이해하기 위해서는 파이썬이 어떻게 설정되어 있는지 이해해야합니다.

ichi.pro

wikidocs.net/32277

 

위키독스

온라인 책을 제작 공유하는 플랫폼 서비스

wikidocs.net

 

관련글 더보기

댓글 영역