오늘도 개발

CPython이 변수를 처리하는 방법 본문

웹 프로그래밍/Python3

CPython이 변수를 처리하는 방법

Sueeeeeee 2022. 6. 1. 23:11

CPython이란?

파이썬은 인터프리터에 따라 다르게 구현된다.

변수를 다루는 방법도 인터프리터에 따라 다르다.

 

CPython은 가장 널리 사용되는 파이썬 인터프리터이다.

여기서는 Cpython이 어떻게 변수를 처리하는지 알아보자.

변수란?

아래 a와 b는 변수이다.

a = 1000
b = 'sue'

 

간단히 말하면 변수는 값을 저장하는 상자이다.

a에 1000을 저장해놓고 필요할 때 꺼내쓴다고 생각할 수 있다.

실제로 변수는 위의 그림과는 좀 다른 방식으로 값을 저장한다.

사실 변수는 값에 대한 이름표에 더 가깝다. 

이게 무슨 말일까?

메모리의 종류 - Heap, Stack

우리가 물품 보관소에 왔다고 생각해보자.

이 물품 보관소에는 물건이 실제로 들어있는 캐비넷 방이 있고

누가 무엇을 맡겼는지 적어두는 장부가 있다.

 

이제 직원을 불러 오리 인형을 맡겨보자.

직원은 적당한 캐비넷에 인형을 넣고

장부에 맡긴 사람의 이름과 캐비넷 번호를적는다.

이제 내가 인형을 찾으러 오면 직원은 장부에 적힌 것을 보고 물건을 찾아올 것이다. 

 

파이썬도 같은 방식으로 값을 저장한다.

파이썬에서는 모든 것이 오브젝트이기 때문에 여기서의 값은 곧 오브젝트이다.

파이썬이라는 물품 보관소에는 오브젝트가 실제로 들어있는 Heap 메모리가 있고,

오브젝트가 어디 있는지 적어두는 장부 역할을 하는 Stack 메모리가 있다.

(이걸 좀 더 개발자답게 말하면 Stack 메모리에는 오브젝트의 레퍼런스가 들어있다고 한다.)

 

우리가 a = 1000이라고 코드에 쓰면

파이썬 물품 보관소의 직원은 Heap 메모리에 1000이라는 오브젝트를 만든다.

그런 다음 Stack 메모리에 a라고 쓰고, 옆에 1000 오브젝트가 위치한 Heap 메모리의 주소를 적는다. 

(이걸 좀 더 개발자답게 말하면 변수 a가 1000 객체를 바인딩했다고 한다.)

* 바인딩 : 변수가 어떤 값을 가리키는 것

id 함수를 이용하면 Heap 메모리의 주소를 실제로 확인할 수 있다.

a = 1000
print(id(a))
# 4390448912

메모리 관리(Memory Management)

파이썬 물품 보관소의 직원이 하는 일이 메모리 관리이다.

캐비넷에 물건을 넣는 것을 메모리 할당(allocation)이라고 하고

필요 없는 물건을 버리는 것을 메모리 해제(deallocation)라고 한다.

 

C, C++같은 언어의 물품 보관소에는 직원이 없다.

우리가 직접 메모리를 할당하고 해제해야 한다.

하지만 파이썬에는 물품 보관소에 상주하는 직원(Garbage collector, GC)이 있어서 알아서 메모리를 관리해준다.

메모리 최적화(Memory Optimazation)

메모리는 한정적이고 아껴 쓸수록 좋다.

그래서 파이썬은 힙 메모리에 이미 존재하는 오브젝트가 있으면

굳이 같은 오브젝트를 또 만들지 않고 있는 오브젝트를 사용한다.

이렇게 오브젝트를 재사용하는 것을 오브젝트 인터닝(Interning)이라고 한다.

 

모든 오브젝트에 항상 인터닝이 적용되는 것은 아니고 

int 자료형의 -5에서 256까지, bool 자료형, 문자열, 리스트 등

적용되는 상황이 몇몇 있다. 

 

다음 코드를 보자. a와 b는 분명 다른 변수인데 같은 주소를 가리킨다.

a = 23
b = 23
print(id(a), id(b))
# 4331990448 4331990448

리스트 요소에도 인터닝이 적용될 수 있다. 

x = "Hello"
y = ["Hello", "world"]

print(id(x), id(b[0]))
# 4563583088 4563583088
# a의 "Hello"와 b의 "Hello"는 같은 오브젝트이다

리스트 변수

여러 요소가 들어있는 리스트는 어떻게 변수에 저장될까?

 

리스트 변수 a는 리스트 오브젝트를 바인딩하고,

리스트 오브젝트의 각 a[0], a[1],...는 리스트의 각 요소를 바인딩한다.

그래서 리스트에 요소를 추가하든 삭제하든 리스트 오브젝트의 주소 값은 바뀌지 않는다.

a = [1, 2]
print(id(a))
# 2704

a.append(3)
print(id(a))
# 2704

print(id(a[0]))
# 5968
print(id(a[1]))
# 6000
print(id(a[2]))
# 6032

리스트 변수의 복사

리스트를 복사해서 변경하려 하는 경우 뜻대로 되지 않는 경우가 있다.

아래 변수 a와 b는 같은 리스트 오브젝트를 가리키기 때문에 a 리스트를 수정하면 b도 똑같이 수정되어버린다.

a = [1, 2, 3]
b = a

print(id(a), id(b)) 
# 4402560448 4402560448

print(a is b) 
# is는 a 오브젝트와 b오브젝트가 같은 오브젝트인지 판단하는 명령어
# True

a[0] = 5
print(b[0]) 
# 5 출력

 

a 리스트를 수정해도 b 리스트가 영향을 받지 않게 하려면

b가 새로운 주소를 가리키게 만들어야 한다.

 

우선 [:]를 이용하여 리스트를 복사하는 방법이 있다.

a = [1, 2, 3]
b = a[:]
a[0] = 5

print(a) # [5, 2, 3]
print(b) # [1, 2, 3]

 

copy 모듈을 사용할 수도 있고

from copy import copy

a = [1, 2, 3]
b = copy(a)

# 2차원 리스트인 경우에는 deepcopy 사용
x = [[1, 2], [3, 4]]
y = copy.deepcopy(x)

 

리스트 자료형의 자체 함수인 copy 함수를 사용할 수도 있다.

a = [1, 2, 3]
b = a.copy()

변수를 만드는 다양한 방법

1) 하나씩 할당

a = 1000
x = y = 2000

2) 리스트, 튜플로 할당

a, b = (1000, 'sue')
x, y = [2000, 3000]

3) 두 변수의 값 바꾸기

x, y = 10, 20
x, y = y, x
print(x) # 20
print(y) # 10

4) 빈 변수 만들기

x = None

 

 

 

참고

점프 투 파이썬 - 02장 파이썬 프로그래밍의 기초, 자료형의 값을 저장하는 공간, 변수

파이썬 코딩 도장 Unit 6. 변수와 입력 사용하기

How does variable and function stored in python

파이썬(python) 메모리 관리 1

Python GC가 작동하는 원리

 

'웹 프로그래밍 > Python3' 카테고리의 다른 글

파이썬 리스트(List)  (0) 2022.06.03
파이썬의 출력 방법  (0) 2022.06.03
파이썬 문자열(String)  (0) 2022.06.01
파이썬 숫자형에 사용하는 연산자  (0) 2022.06.01
파이썬의 자료형  (0) 2022.06.01