mutable과 immutable

si_yeon·2021년 12월 29일
0
  • mutable (가변) 객체
    -list, dictionary, set 등
    -객체 생성 후 객체의 값을 바꿀 수 있음
    -변수는 값이 수정된 객체를 가리키게 됨

  • immutable (불변) 객체
    -int, float, string, tuple 등
    -객체를 생성한 후 객체의 값을 바꾸는 것은 불가
    -변수는 해당 값을 가진 다른 객체를 나타냄

    여기에 쉽게 설명되어 있음

https://webnautes.tistory.com/1181
이 블로그의 내용을 바탕으로 이해한 것 정리하려고 함.

파이썬에서 모든 것은 객체(object)이고 객체가 생성된 후 id는 변하지 않는다. id는 python에서 객체가 실제 저장된 메모리 주소를 나타낸다.

id함수를 이용하면 객체의 id를 알 수 있는데,
위의 블로거는 id 함수is 연산자를 통해 mutable한 객체와 immutable한 객체를 비교했다.

즉, 변수에 대입한 값을 수정한 뒤 id함수로 비교하는 것.
같으면 mutable(가변)객체, 다르면 immutable(불변)객체가 되는 것.
(값은 같을 수 있어도, 저장된 주소는 다를 수 있기 때문)

변수

  • 변수는 값을 담는 그릇, 포인터 정도로 이해하면 된다.
    이 때 변수는 저장공간을 할당받지 않으며 그 데이터값(객체)를 가리키기만 한다.
  1. 변수를 새로운 객체에 대입하거나 다른 변수에 대입하는 경우에서의 mutable과 immutable 객체간 차이

    1) mutable 객체_ ex. list

    • a = [1, 2, 3]
      b = a
      a is b >> True

      a.append(4)
      a is b >> True

      #a의 값과 b의 값을 보여줌
      a;b
      >> [1, 2, 3, 4]
      [1, 2, 3, 4]

      즉, 변수 a와 a가 저장된 변수b는 같은 주소를 가리키고 있기 때문에 변수 a의 값이 변해도 주소가 바뀌지 않음.

    2) immutable 객체_ ex. int

    • a = 1
      b = a
      a is b >> True

      #둘은 같은 객체를 가리키고 있음

      a = 2
      a is b >> False
      #둘은 다른 객체를 가리키고 있음

      a;b
      >>2
      1

      즉, 불변객체인 int는 변수의 값이 변하면 새로운 주소를 할당한다.

얕은복사(shallow copy)와 깊은복사(deep copy)
참고 블로그

얕은복사와 깊은복사는 객체가 다른 객체를 포함하고 있는 경우(복합객체)를 통해 잘 이해할 수 있다.

  • 얕은복사(shallow copy)

    import copy
    a = [1, [1, 2, 3]]
    b = copy.copy(a)   # a를 얕은 복사한 것
    print(b)   >> [1, [1, 2, 3]]
    
    b[0] = 100
    print(b)   >> [100, [1, 2, 3]]
    print(a)   >> [1, [1, 2, 3]]
    
    c = copy.copy(a)   # a 얕은 복사
    c[1].append(4)
    print(c)   >> [1, [1, 2, 3, 4]]
    print(a)   >> [1, [1, 2, 3, 4]]

 - 두번째 블록을 보면 b에서 변경된 원소가 a에는 반영되지 않는다.
 반면, 세번째 블록의 경우 c에서 변경된 원소가 a에도 반영이 되었다.
 
 - b의 수정값이 a에서 적용되지 않은 이유는 
 100과 1 모두 immutable객체(int)이기 때문에
 값이 바뀌자마자 새로운 주소를 할당한다.
 
 - c의 내부리스트[1, 2, 3]이 [1, 2, 3, 4]로 변경된 이유는 
 이 내부 객체가 mutable객체(list)이기 때문이고, mutable객체는 같은 주소를 참조한다. 
 
 - 즉, 얕은 복사는 복합객체의 틀만 복사한다. 복합객체 속의 객체
 (내부리스트)은 복사하지 못한다는 것. 
  • 깊은복사 (deep copy)
import copy

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

b[0] = 100
b[1].append(4)
print(b)   >>> [100, [1, 2, 3, 4]]

print(a)   >>> [1, [1, 2, 3]]

- 깊은 복사의 경우 복합객체의 내부객체까지 모두 복사한다.
따라서, b에서 변경한 내용이 a까지 미치지 못한다.

정수 (Integer)

immutable한 객체이므로, 수정하면 새로운 객체가 생성된다.

예를 들어 1이라는 정수를 a에 대입한 값(a = 1)과 그냥 1이라는 정수는 같은 주소값(id(a) == id(1))을 가지지만**, 이 변수 a에 1을 더한 값을 다시 a에 저장하면(a = a + 1) a는 이전의 a와는 다른 새로운 객체가 되어 다른 주소값을 가진다.

** 정수 -5 ~ 256 까지는 효율성을 위해 기존 메모리에 생성되어 있는 객체를 참조한다. 따라서 a = 1 과 b = 1에서 a와 b의 주소값은 같다. 마찬가지로 변수 a에 대입한 1과 그냥 1의 주소값도 같다.

이 범위를 벗어나게 되면 새로운 주소를 할당하는데 변수에 대입되기 전까지는 같은 메모리 위치를 재사용한다.

예를 들어, 변수에 대입하지 않은 257이라는 값과 변수에 대입하지 않은 258이라는 값의 메모리 위치는 같다.
(id(257) == id(258))
257을 변수에 대입하게 되면(a = 257), 258은 다른 메모리 위치를 가진다. (id(a) != id(258))

뭐라고 쓴지 모르겠다. 나중에 수정해야지

0개의 댓글

관련 채용 정보