
mutable과 immutable 하다는 표현들은 코딩 공부를 하다보면 자주 보게된다.
이들의 뜻은 간단히 객체의 '변경 가능'과 '변경 불가능'을 의미한다.
하지만 단순하게 변경 가능 여부로 정의하기에는 조금 아쉬운 설명이다.
따라서 조금 더 디테일하게 알아보도록 하자.
| 종류 | |
|---|---|
| mutable | list, set, dictionary |
| immutable | int, float, bool, str, tuple |
a = 1
print(id(a))
a = 2
print(id(a))
예를 들어 a = 1이라고 작성했을 때, a라는 변수가 1이라는 객체를 참조한다.
그런다음 a = 2로 변경했을 때, a는 2라는 객체를 참조한다.
immutable한 1 (int)을 바꾸지 못하기 때문에 새로운 메모리 공간을 확보하고 a가 2를 참조하도록 하는 것이다.
print문은 주소값이 찍힐텐데 두 값이 다른 것을 확인할 수 있을 것이다.
immutable객체는 변경하지 못한다고 했을 때, 문자열에 대한 의문이 있을 수 있다.
replace같은 함수나 +를 통해 값을 변경할 수 있기 때문이다.
이는 기존 객체를 변경하는 것이 아니고, 값을 복사하여 새로운 메모리 공간에 할당해주는 것이다.
이들도 마찬가지로 변경 전 후의 id값을 찍어보면 다른 것을 알 수 있다.
lst = [1, 2, 3]
print(id(lst))
lst[1] = 4 # [1, 4, 3]
print(id(lst))
lst.append(6) # [1, 4, 3, 6]
print(id(lst))
list는 mutable한 객체이다. 따라서 인덱스를 이용하여 값을 변경하거나, append로 값을 추가 하여도 주소값에는 변화가 없는 것을 확인할 수 있다.
hashable이라는 개념은 '값의 비교'를 위해 존재한다.
hash라는 함수는 hashable object가 인자로 들어갔을 때 어떤 정수 하나를 반환해준다.

hash의 값이 도중에 변경되면 안되기 때문에, key로 immutable한 값을 요구한다.
그러면 모든 immutable한 객체는 hashable한지에 대한 생각이 떠오를 수 있는데,
결론적으로 이는 그렇지 않다고 할 수 있고, 자세한 얘기는 뒤에 설명한다.
중복여부를 판단하는 set이나 dictinary의 key들이 hashable해야한다.
tp = (1, 2, 3)
tp[1] = 4
# TypeError: 'tuple' object does not support item assignment
tuple은 immutable하므로 일반적으로 변경할 수 없다.
tp = (0, 1)
print(id(tp))
tp += (2,) # (0, 1, 2)
print(id(tp))
다만 위와 같이 str 처럼 복사를 통한 새로운 값을 할당하여 변경하는 것은 가능하다.
새로운 주소를 가지기 때문에 print값이 다른 것을 확인할 수 있다.
그러나 예외의 상황이 있다.
tp2 = (0, [1, 2, 3])
print(id(tp2))
tp2[1].append(4) # (0, [1, 2, 3, 4])
print(id(tp2))
위와 같이 tuple의 값으로 mutable한 list를 가질 수 있다.
tp2[1]는 mutable하므로 값을 추가할 수 있다.
tp2가 참고하는 값을 변경시키는 것이 아니므로 이런 변경이 가능하고 주소값 또한 변경되지 않은 것을 확인할 수 있다.
앞에서 말한 list를 가지는 tuple은 immutable한 동시에 값의 변경이 일어날 수 있다.
hashable의 key 값으로는 변경되는 것이 오면 안되기 때문에 위 같은 경우의 tuple은 hashable하지 않다고 할 수 있다. (immutable한 값만 가지는 tuple은 hashable하다고 할 수 있다.)