참조에 의한 변수와 객체 연결

Python의 변수와 참조

변수는 일반적으로 데이터를 저장할 수 있는 메모리 공간을 의미한다.
다만, 파이썬에서의 변수는 C, 자바 같은 컴파일 언어에서의 변수와는 차이가 있다.

자바를 예로 들면 자바는 변수를 선언하면서 선언된 자료형 만큼의 메모리를 확보한다. 더 정확하게 말하면 원시 타입(Primitive Type)에 해당하는 변수(int, double, boolean 등)를 선언하면 선언된 타입 만큼의 크기의 영역을 Stack 메모리에 선언한다. 그리고 객체와 메서드 같은 참조형 타입(Reference type)은 Heap 메모리에 실질적인 데이터가 저장되고 그 데이터의 주소값이 stack 메모리에 저장되는 형태이다.

하지만 파이썬의 변수는 다르다.
파이썬에서 변수는 타입에 의해 선언되는게 아닌 객체와 연관되어 있다.
왜냐하면 변수에 선언되는 데이터는 모두 객체이기 때문이다.
아래에서 조금 더 구체적으로 살펴보겠다.

만약
a = 10 이라는 python 구문이 있다면,
파이썬은 우선 10을 나타내는 객체를 생성한다.
이후 변수 a를 생성하고 변수 a와 객체 10을 연결한다.
즉, a와 객체 10은 다른 위치에 저장되고 이 둘은 참조에 의해 연결된다.

다른 예시를 살펴보면

a = 10
a = "ten"

이 경우 a의 타입이 정수타입에서 문자열타입으로 변경된 것이 아니라
변수 a가 객체 10을 참조했다가, 객체 "ten"을 참조하는 것이다.
왜냐하면 파이썬에서의 변수는 타입을 가지지 않는다. 그래서 a의 타입은 변경할 수 없다.
그래서 변수는 사실상 특정 객체를 참조하고만 있는 것이다.

그렇다고 파이썬에 타입이 아예 없는 것은 아니다.
객체들이 타입 정보를 갖고 있다. 각각 객체의 헤더에 타입 정보가 저장된다고 한다. 이처럼 객체 자신이 자신의 타입을 알고 있으므로 변수에 타입을 저장할 필요가 없다.

그러면 이런 생각이 들 수 있다.

a = 10
b = 10

이 경우 10과 10은 같은 객체 인건가? 그렇다면 a에 +5를 하면 b의 값도 변하는 것인가?
하나씩 답을 해보면 아래와 같다.

10과 10은 같은 객체이다.

이는 파이썬 구문으로 확인 가능하다.
파이썬에서 == 는 값이 같은지 확인하고 'is'는 같은 객체를 참조하고 있는지를 확인해 준다.

a = 10
b = 10
a == b
#--> True
a is b
#--> True

10은 같은 객체임을 확인할 수 있다.
그렇다면, a를 수정하면 b 또한 수정되어야 하지 않을까?

a에 5를 더해도 b의 값은 변하지 않는다.

a = 10
b = 10
a += 5
a
#--> 15
b
#--> 10

b의 값은 변하지 않는다. 분명 같은 객체라고 했는데 왜 값이 변하지 않는지 의문이 들 수 있다. 필자 또한 그랬다.
이는 파이썬의 가변 객체와 불변 객체를 생각해 보면 이해하기 쉽다.

파이썬에서 int는 불변 객체이다. 즉 int 타입의 객체는 값이 변하지 않는 다는 것이다.
즉, 우리가 '+= 5'를 한 행위는 객체 값에 변화를 준게 아니다.
파이썬에서는 a가 참조하는 값이 10에서 15로 변한 것이다.

여기서 또 깨닫는 사실이 있다.

list_1 = [1,2,3]
list_2 = list_1
list_1[0] = 10
list_2
#--> [10,2,3]

필자는 이 구문을 이해하지 못하고 리스트를 복사하려면 얕은 복사(shallow copy), 깊은 복사(deep copy)가 필요하다고 단순하게 암기했었다.
하지만 앞의 개념을 적용시키면 이는 매우 당연하다.

list_1과 list_2는 같은 [1,2,3] 객체를 참조한다.
그리고 list는 가변 객체이다. 값이 변할 수 있다.
그래서 List_1[0] = 10 이 구문은 list_1이 다른 객체를 참조하도록 하는 구문이 아니라, list_1이 참조하는 객체 자체를 바꾼 것이다.
그래서 같은 객체를 참조하는 list_2의 출력값도 바뀌는 것이다.

 

 

'Python > Python' 카테고리의 다른 글

파이썬에서 Function과 method의 차이  (0) 2023.03.20
Python 에서의 Lambda method  (0) 2023.02.22
Python에서 집합을 사용하는 이유  (0) 2023.01.10
불변성과 문자열 수정  (0) 2023.01.06
반내림 vs 내림(Python3)  (0) 2023.01.05