[파이썬 | Python] Mutable object, Immutable object
study/others

[파이썬 | Python] Mutable object, Immutable object

파이썬의 모든 것은 객체(object)이다.

거의 모든 객체는 속성(attributes)과 메서드(methods)로 이루어져 있으며, 객체끼리의 식별은 id(object)를 통해서 한다. id가 같다면 동일한 객체, 그렇지 않으면 다른 객체이다.

id는 해당 객체를 가리키는 유일한 상수(unique constant)이며, 객체가 서로 같은지 비교를 위해서는 $==$ 가 아닌 is 를 사용한다.

C언어의 포인터와 같은 개념이지만, 실제로 id가 가리키는 것이 메모리의 주소를 의미하는 것은 아니다.

 

객체는 변경 가능하거나, 그렇지 않다. 이것이 mutable object와 immutable object의 차이이다.

 

쉬운 예로,

a = "abc"
a.replace("a", "x")
# a는 여전히 "abc"이다

a = [3, 2, 1]
a.sort()
# a는 [1, 2, 3]으로 바뀌었다

str.replace()만으로 str의 값이 변하지 않는다. 반면에, list.sort()는 메서드를 부르는 것 자체로도 리스트가 정렬된다(값이 변한다).

 

조금 더 깊게 들어가면,

a = 100
b = a
id(a) == id(b) == id(100) # True
a += 1
id(a) == id(b) # False

처음 a와 b는 같은 id를 가진다. (같은 객체이다)

하지만 a의 값을 1 올리는 순간, b는 a를 따라가지 않는다. int는 immutable object이기 때문이다.

int의 100이 101로 바뀌는 것이 아니라, a가 가리키는 객체가 101을 가리키게 되며,  a와 b의 id가 달라지게 된다.

list의 경우는 다르다.

a = [1, 2, 3]
b = a
a[0] = 0 # b[0]의 값도 변하게 된다.
print(a, b) # [0, 2, 3] [0, 2, 3]

 

list는 대표적인 mutable object이다. a와 b는 같은 id를 가지지만, a의 원소를 수정한다고 해서 a의 id가 바뀌지 않는다. list 자체가 값이 바뀌게 된다.

 

대표적으로 list, dict가 mutable object이고,

str, int, tuple 등이 immutable object이다.

immutable object를 변경한다고 쉽게 생각하지만, 파이썬의 내부에서 위와 같은 동작을 통해 두 개의 객체를 가리키도록 만든다.call by value, call by reference와 비슷한 맥락인 것 같다!

 

 

 

프로그래밍 문제를 풀 때 파이썬에서 리스트 값을 복사해야 할 때가 종종 있다. 이럴 경우에는 [x for x in list] 와 같은 list comprehension으로 작성해주면 된다. 이럴 경우에는 새로운 list에 하나하나 append하는 꼴이 된다.

+ 2차원 이상의 list의 경우, for x in list의 x 또한 list object이기 때문에, list comprehension을 2중으로 작성해야 한다.

-> [[x for x in list] for list in _2d_list]

deepcopy()와 같은 메소드가 존재하긴 하지만, 메모리를 많이 잡아먹기 때문에 웬만하면 2-3중 정도는 위와 같이 작성한다.

(물론 시간은 원소의 수에 비례한다)

 

References

https://stackoverflow.com/questions/865911/is-everything-an-object-in-python-like-ruby

https://ledgku.tistory.com/54

https://webnautes.tistory.com/1181

https://docs.python.org/3/library/functions.html#id