파이썬의 가변/불변 객체

Created
Nov 19, 2020
Created by
Tags
Python
Property
 
 
파이썬의 참조(reference) 방식은 기존에 알고 있던 참조방식과 좀 다르다.
 
int a = 10; int &b = a; b = 7 std::cout << a << std:endl;
 
위 c++ 코드를 실행하면 7이 출력될 것이다. 포인터 ab가 참조하는 메모리 공간이 같기 때문이다.하지만 파이썬은 다르다.
 
a = 10 b = a print(id(a)) >> 140409867117088 print(id(b)) >> 140409867117088 b = 7 print(id(a)) >> 140409867117088 print(id(b)) >> 140409867117136
 
b = 7 으로 새로운 값을 할당하면 ba가 가리키는 메모리 공간을 더 이상 참조하지 않는다. b는 7이라는 새로운 객체를 참조한다. 정수 7은 불변(immutable) 자료형이기 때문에 참조 변수를 통해 값을 바꿀 수 없기 때문이다.
 
파이썬에서는 모든 것이 객체다. boolean, int, float 등 다른 언어에서 원시 타입(primitive type)으로 분류하는 값들도 객체로 취급한다. 객체는 불변과 가변으로 나뉜다.
 
파이썬 자료형의 불변/가변 여부
클래스
설명
불변/가변
불리언
불변
정수
불변
실수
불변
문자(열)
불변
튜플
불변
리스트
가변
중복을 허용하지 않는 집합
가변
딕셔너리
가변
 
따라서 b가 가리키는 7도 int 클래스의 객체고, b는 객체가 점유하는 메모리를 가리키는 포인터라고 할 수 있다.
>>> type(b) <type 'int'> >>> type(b.__class__) <type 'type'>
 
문자/숫자 같은 불변 객체는 변경이 불가능하기 때문에 참조 변수를 통해 조작할 방법이 없으나 리스트, 집합, 딕셔너리와 같은 가변 객체는 참조 변수를 통해 객체를 변경할 수 있다. 하지만 가변 객체의 경우에도 = 연산자로 다른 객체를 참조 변수에 할당하면 다른 ID를 갖게 된다.
 
>>> a = [1, 2, 3] >>> b = a >>> id(a) 4522271376 >>> id(b) 4522271376 >>> b[1] = 3 >>> b [1, 3, 3] >>> a [1, 3, 3] >>> b = [4, 5, 6] >>> id(b) 4522271520
 
 

ss[:]의 차이

 
어떤 리스트 s가 있다고 하자. id(s)id(s[:])는 서로 다르다. s[:]s를 deep copy 한 것이기 때문이다.
>>> s = [1, 2, 3] >>> id(s) 4522271592 >>> id(s[:]) 4522109408
 
반면에 s[:]s[::-1]은 리스트의 인덱스들이 참조하는 메모리주소의 순서가 서로 반대일 뿐 동일한 메모리 공간을 참조한다. (리스트 내 각 원소는 연속된 공간에 있다.)
>>> id(s[::-1]) 4522109408 >>> s2 = s[::-1] >>> id(s2[-1]) 140409867117256 >>> id(s[0]) 140409867117256 >>> id(s2[0]) 140409867117304 >>> id(s[-1]) 140409867117304
notion image
 
 
s[::-1]s를 deep copy 한 것이므로 s = s[::-1]s가 참조하던 메모리 공간을 더 이상 참조하지 않고 s[::-1]이 가리키는 공간을 참조하도록 한다.
>>> s = [1, 2, 3] >>> id(s) 4522109408 >>> id(s[::-1]) 4522271592 >>> s = s[::-1] >>> id(s) 4522271592
 
반면에 s[:] = s[::-1]s[:]의 각 인덱스가 가리키는 주소를 바꾼다.
>>> s2 = s[:] >>> s3 = s[::-1] >>> id(s2[0]) 140409867117304 >>> id(s3[0]) 140409867117256 >>> s2 = s3 >>> id(s2[0]) 140409867117256