목차

  1. Everything is object in Python
  2. 파이썬의 메모리 구조
  3. 파이썬에서의 Heap 사용
  4. 파이썬에서의 메모리 할당 과정

Everything is object in Python

x = 10
print(type(x))

>> <class 'int'>

C에서

x = 10 

이렇게 변수를 할당하면, 메모리에 해당 값이 바로 저장되지만

 

파이썬에서

x = 10

이렇게 변수를 할당하면, int라는 object를 만들어서 변수 x가 그 객체를 가리키는 형태입니다.

 

x의 타입을 출력해보면 class가 나오는데, class를 구체화 한 것이 object입니다.

 

Class와 Object에 대한 설명

더보기
더보기

class와 object를 간단히 설명하자면

class는 추상적인 것이고, object는 구체적인 것이라고 생각하면 됩니다.

파이썬에서 존재하는 타입은 class로 정의 됩니다. class의 예로는 list나 tuple 등이 있습니다.

class는 타입을 정의하는 것일 뿐입니다.

파이썬으로 우리가 list를 만들 때는, 사실 class를 사용해서 object를 만드는 것입니다.

 

보통 Reference 라고 하며, 포인터의 개념과 비슷합니다.

 

y = x
if (id(x)==id(y)):
	print("x 와 y 는 같은 객체를 가리킨다")
    
>> x와 y는 같은 객체를 가리킨다

그리고

y = x

라고 하면, x에 의해서 이미 만들어진 10이라는 int object를, y가 그냥 가르키기만 합니다.

그래서 x와 y는 10이라는, 같은 int object를 가리키는 것입니다.

 

따라서, int object 10을 가리키는 것은 x 와 y 입니다.

 


x = x + 1
if (id(x) != id(y)):
	print("x와 y는 다른 객체를 가리킨다")

>> x와 y는 다른 객체를 가리킨다.

x = x + 1 은 

11 (10 + 1)이라는 새로운 int object를 생성합니다.

그리고 x는 새로 만들어진 int object를 가리킵니다.

 

z = 10

if (id(y)==id(z)):
	print("y와 z는 같은 memory를 가리킨다")
else:
	print("y와 z는 다른 object를 가리킨다")
    

>> y와 z는 같은 메모리를 가리킨다

z = 10 은

10이라는 int object를 가리키는데,

int object 10은 이미 생성이 되어 있으니 만들 필요가 없고, 그냥 z가 10을 가리키기만 합니다.

 


z = Car()
print(type(z))

>> <class'__main__.Car'>

z = Car( )에서

Car라는 object가 생성되고

z는 Car object를 가리킵니다.

 

따라서 z의 type은 Car 입니다.


파이썬 메모리 구조

Text 영역(= 코드 영역) : 실행할 프로그램의 코드가 저장됩니다. CPU는 텍스트 영역에 저장된 명령어를 하나씩 가져가서 처리합니다.

Data 영역 : 전역 변수와 정적 변수를 저장하는 공간이며, 프로그램 시작과 함께 할당되며, 프로그램이 종료되면 소멸됩니다.

Stack 영역 : 지역 변수와 매개변수를 저장하는 공간이며, 함수의 호출과 함께 할당되며, 함수의 호출이 완료되면 소멸됩니다.

Heap 영역 : 사용자의 동적 할당으로 생성되는 공간이며, 사용자가 공간의 크기를 직접 관리할 수 있습니다.

 

Heap 영역의 크기는 프로그램이 실행되는 도중인 런타임에 사용자가 직접 결정하게 됩니다. 반면에 데이터 영역과 스택 영역의 메모리 크기는 컴파일 타임에 미리 결정됩니다.

 

예를 들어 게임 회원수가 1000명이고, 동시 접속자 수는 10%인 100명 정도인 게임을 운영하는 회사가 있다고 합시다. 게임 회원수가 1000명이라고 해서 1000명분의 메모리를 고정적으로 지정하면 그 중 10%만 메모리가 사용되고, 나머지 90%는 사용되지 않은 채로 메모리 공간만 잡아먹게 됩니다. 그러면 비생산적이고 비효율적이게 됩니다. 하지만 회원이 게임을 접속할 때만(프로그램이 실행되는 도중인 런타임 때) 동적할당을 사용하게 되면, 사용자가 게임을 접속할 때 필요한 메모리만 할당 받게 됩니다. 그렇게 하면 더욱 효율적이고 생산적으로 메모리를 관리할 수 있게 됩니다.

 

이러한 이유로 동적 할당으로 힙 영역을 적절한 곳에 사용하게 된다면 메모리의 낭비 없이 생산적으로 메모리를 할당할 수 있게 됩니다. 런타임에 메모리가 할당받는 것을 메모리의 동적 할당(dynamic allocation)이라고 합니다.

 


파이썬에서의 Heap 사용

C나 java의 경우 malloc 함수를 이용해서 동적 할당을 할 수 있습니다. 하지만 파이썬은 동적 할당의 기능이 없습니다. 이 말은 즉슨, 사용자가 직접 메모리 할당 범위를 조정하지 않는다는 말입니다. 왜냐하면 파이썬은 자동으로 메모리를 관리해주는 언어이기 때문입니다.

 

그럼 파이썬은 Stack 영역만 사용하게 되는가? 그렇지 않습니다. 파이썬은 메모리를 관리해주는 특별한 기능이 있습니다.

바로 Python Memory Manager 라는 기능인데요, 이 기능이 포인터를 움직여서 Heap 영역의 메모리 할당 범위와 내부 버퍼를 조정해줍니다. Python Memory Manager 는 Python/C API를 통하여 스토리지를 동적으로 관리합니다. 스토리지의 동적 관리가 필요할 때는 메모리의 공유(share), 메모리의 세분화(segmentation), 메모리의 사전 할당(preallocation), 그리고 캐싱(caching)이 있습니다.

 

파이썬에서의 메모리 동적 할당은 C와 다르게 그리 중요하지가 않습니다. 그렇기 때문에 C에서 사용하는 동적할당 API를 호환하여 사용하고 그렇기 때문에 Python/C API라고 불립니다. 이 API중 사용하는 함수는 malloc(), calloc(), realloc(), free()등이 있습니다.

 

Heap 안의 메모리 영역을 interpreter가 포인터를 사용해 영역의 범위를 조정함으로써, interpreter가 자동으로 메모리를 OS로 할당하지 않고 가지고 있다가, 사용될 때 메모리를 재사용하는 방식으로 운영됩니다. 즉, 메모리 할당에 있어서 OS의 과부하를 줄여주는 획기적인 High level language 입니다.

 

변수와 함수가 호출됨에 따라 그에 맞는 메모리를 그때그때 Python Memory Manager가 운영체제와 소통하면서 할당하고 결과값이 return되거나 변수와 함수가 사용을 멈추었을 때, 바로 메모리가 소멸되는 형식이라고 할 수 있겠습니다.


파이썬에서의 메모리 할당 과정

def f2(x):
    x = x + 1
    return x
    
def f1(x):
    x = x * 2
    y = f2(x)
    return y

#main
y = 5
z = f1(y)

 

main 함수에서 y = 5 와 f1(y) 를 호출합니다.

f1(y)를 호출하면 Stack 영역에 f1( ) 영역이 생성됩니다.

 

그러면 f1 영역에서 x = x*2 로 인해

int object 10이 생성되고

x는 int object 10를 가리킵니다.

 

그리고 f2(x)를 호출하면 Stack 영역에 f2( ) 영역이 생성됩니다.

 

그러면 f2( ) 영역에서,

x = x+1로 인해,

int object 11이 생성되고

y는 int object 11를 가리킵니다.

 

파이썬의 Stack과 Heap에는 위와 같이 저장됩니다.

 


할당 해제

먼저 Stack의 가장 위에 있는 f2( ) 가 해제 됩니다.

그 다음 f1( )가 해제 되는데, f1( )의 변수 x가 없어짐에 따라 int object 10도 사라집니다.

왜냐하면 int object 10은 아무것도 가리키지 않기 때문입니다.

 

이것이 바로 reference counting이 0이 됨에 따라서 object가 사라지는 Garbage collector 입니다.

파이썬은 reference counting을 이용해서 메모리를 관리합니다.

 

f1( )이 해제 될 때, int object인 10이 사라지는 것이 대표적인 예 입니다.

 

마지막으로 main 함수의 변수 z는 11을 가리킵니다.

 


Ref

https://www.youtube.com/watch?v=arxWaw-E8QQ 

 

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

Python - Multithreading  (0) 2022.06.14
Mac - Conda가 안될 때, anaconda 터미널이 안켜질 때  (1) 2021.06.16
Python - 시각화 기초2  (0) 2021.01.31
Python - 시각화 기초  (0) 2021.01.27
Python - Numpy 기초  (0) 2021.01.27
복사했습니다!