본문으로 바로가기

변수의 정의

일반적으로 변수란 데이터를 저장할 수 있는 메모리 공간 자체를 의미한다. 변수는 숫자와 문자 뿐만 아니라 객체, 혹은 함수(람다 함수)까지도 담을 수 있다. 변수에 담긴 값이나 가리키는 대상은 프로그램 실행 도중에 언제라도 변경될 수 있다. 언제든지 값이 변경될 수 있어서 변수라고 하는 것이다.

Python의 변수가 다른 언어와 다른 점

Python의 변수는 다른 언어와는 약간 차이가 있다. 다른 언어들이 값이 담겨 있는 공간의 별칭을 '변수'(variable)라고 말한다. 그러나 파이썬은 변수라는 메모리 공간에 값을 직접 저장하지 않는다. 알다시피, 파이썬에서 사용되는 모든 것(변수, 클래스, 함수 등등)들은 '객체'이다. 우리가 변수에 저장한다고 생각한 '객체'들은 실제로는 다른 메모리 공간에 저장되어 있고, 변수는 값 객체를 가리키고만 있다. 따라서 숫자나 문자도 모두 객체인 파이썬에서는, 동일한 객체의 값의 경우에는 같은 주소값을 가진다.

num과 temp에 숫자 객체를 넣고, 각각 어떤 주소값을 가리키고 있는지 살펴보자. 터미널에서 Python을 쳐서 Python의 interpreter를 실행시켜 아래의 코드를 쳐보면 이해하기가 쉽다. 물론 컴퓨터가 프로그램을 실행시킬때마다, 그리고 각자의 컴퓨터마다 객체를 저장하는 위치가 변경될테니 주소값 자체는 아래의 결과값이라는 다르게 나올 것이다. 여기서 우리가 주목해서 보아야 할 점은 num과 temp의 주소값이 일치하는지 여부이다.

Step 1. 변수 선언

num과 temp가 10이라는 같은 값을 가지니 모두 동일한 주소값을 담고 있다.

1
2
3
4
5
6
7
8
num = 10
temp = 10
 
 
# 변수가 가리키고 있는 객체의 메모리의 주소값
# num, temp 모두 동일한 주소값을 담고 있다.
id(num)  # '4420898256'
id(temp)  # '4420898256'
cs

 

Step 2. temp의 값을 변경

temp의 값을 20으로 변경해보자. num에는 여전히 10이 담겨 있다. temp의 값을 변경하고 나니 temp에는 num과는 다른 주소값을 출력한다.

1
2
3
4
5
6
7
8
9
num = 10
temp = 10
 
 
# temp 변수의 값을 변경한다.
# temp의 주소값이 변경되어 num, temp가 서로 다른 주소값을 담고 있다.
temp = 20
id(num)  # '4420898256'
id(temp) # '4420898576'
cs

 

Step 3. temp의 값을 본래 값으로 변경

temp의 값이 20으로 변경된 상태에서, 다시 한번 temp의 값을 10으로 변경해보자. 두 변수가 다시 동일한 주소값을 출력한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
num = 10
temp = 10
 
# 변수가 가리키고 있는 객체의 메모리의 주소값
# num, temp 모두 동일한 주소값을 담고 있다.
id(num)  # '4420898256'
id(temp)  # '4420898256'
 
temp = 20
 
# temp를 다시 num과 같은 값으로 변경한다
# 다시 동일한 주소값이 되어 같은 '값 객체'를 가리킨다.
temp = 10
id(num)  # '4420898256'
id(temp)  # '4420898256'
cs

is 문법을 사용한 주솟값 비교

지금까지 보아온 결과대로라면 긴 문자열이나 긴 숫자의 경우에는 바로 이 주솟값을 가지고 같은 값을 가지고 있는지 비교할 수 있다. 파이썬의 변수는 같은 값이면 같은 주솟값을 가질테니 말이다. 하지만 아래의 코드를 돌려 보면(Python 3.6.5 버전) is로 비교하였을 때와 '=='로 변수의 값을 비교했을 때 결과가 다르다고 나온다. 아마도 문자열을 곱셈하는 과정에서 내부적으로 변수가 값 객체를 가리키는 방식이 달라지는 것으로 추측된다. 

1
2
3
4
5
6
= 'hello world this is a long long string'*2
= 'hello world this is a long long string'*2
print(id(d)) # 4349782576
print(id(e)) # 4349783088
print(d is e) # False
print(d == e) # True
cs

결론

결론적으로 파이썬의 변수가 어떻게 동작하는지를 이해하기만 하고 is 구문을 사용하여 값을 비교하는 것은 조심해야할 것 같다. (고수님들은 내부적인 코드를 살펴보고 왜 이러는지 알려주시면 감사하겠습니다) 단, 이러한 파이썬 변수의 동작 방식, 파이썬에서는 변수에 값을 바로 담는 것이 아니라, 값 객체는 별도의 공간에 저장되고 변수에는 그 값 객체가 담긴 공간의 주솟값을 가리킨다는 부분은 확실히 이해해두는 것이 좋다.  파이썬이 인자를 전달할때의 방식이 '참조에 의한 전달'도 '값에 의한 전달'도 아닌 '객체 참조에 의한 전달' 방식으로 인자 값을 전달하는데 나중에 이 점을 쉽게 이해하기 위해서다. 

참고

Python Optimizations