본문 바로가기

Python

note 1

반응형

>>>  a = -

>>>  a is -

 True 


>>>  id(a), id(-5

ex)  10000001, 10000001 


>>>  a = -

>>>  a is -

 False 


>>>  id(a), id(-6

ex)  10000003, 10000109 


두 가지 케이스가 다르게 나오는 이유 (파이썬 3.8.10)

  • 파이썬은 기본적으로 동적 메모리 할당을 베이스로 RAM의 [파이썬 영역]의 [heap 영역]에서 관리한다.
  • 하지만 예외적으로 정수 중 일부인 '작은 정수'(상수값)들은 정적 메모리 할당을 한다.
  • 작은 정수들은 [파이썬 영역]의 [data 영역]에서 관리한다.
  • 정적 메모리 할당은 파이썬 인터프리터가 RAM에 상주하게 되면 메모리 공간을 가지게 되어있다.
  • 변수에 상수값을 대입할 경우 해당 값의 주소 자체를 참조하여 [stack 영역]에 있는 변수에게 입력한다(call by value).
  • 일반 정수와 파이썬의 대부분에선 동적 메모리 할당을 하기 때문에 해당 값을 사용할 때 공간을 부여해 주고 그 주소를 참조하는 값을 [stack 영역]에 있는 변수에 대입하게 된다. (call by reference).
  • 정적 할당은 메모리 공간이 고정되어 있기 때문에 a 와 -5 의 주소가 같은 곳으로 확인된다.
  • 동적 할당은 메모리 공간이 사용 시마다 배치되기 때문에 a 와 -6 의 주소가 다른 곳으로 확인된다.
  • 바로 위 내용을 토대로 a = -6 을 여러 번 반복해서 대입해 보면 두 객체 모두 주소가 계속 달라짐을 확인할 수 있다.

- 작은 정수란?

파이썬에서 -5 ~ 256 까지의 수를 일컫는다. 이는, 모든 정수를 다 정적으로 할당하기엔 범위가 무한정이어서 자주 사용되는 숫자들인 상수값으로 정해 '상수 최적화'를 하여 메모리를 여러 번 할당하지 않게 미리 interning 하여 사용한다.


내용을 확인하면서 들었던 의문

ㅡ chatgpt 와 대화(기억나는 대로 기재)를 기반으로 작성하여 오류가 있을 수 있으니 추후 수정 필요

red_jh : 작은 정수란?

chatgpt : 파이썬에서 -5 ~ 256 까지의 수를 일컫는다.

 

red_jh : 왜 -5 ~ 256 이고 왜 이 정수들만 정적 할당이고, 외에는 동적 할당인가?

chatgpt : 모든 정수를 다 정적으로 할당하기엔 범위가 무한정이서 자주 사용되는 숫자들인 상수값으로 정하고 보니 -5 ~ 256이 되었다. 이것은 파이썬 인터프리터마다 다를 수 있다.

 

(이 의문은 무의식적으로 파이썬의 기본 구동이 정적 할당으로 생각하고 있었기 때문에 나온 의문으로써 사실 동적 할당이 베이스이며 메모리 효율을 위해 예외적으로 정적 할당을 하게된 케이스라고 생각하면 이해가 되는 부분이다.)

 

red_jh : 메모리 주소를 직접 참조(call by value)와 주소를 참조하는 값(call by reference)의 차이는?

chatgpt : call by value 는 변수가 값을 직접 활용하는 것이고, call by reference 는 주소를 참조하는 값을 활용하는 것이다.

 

(이 의문은 메모리 영역의 활용 방법에 대해 오인하고 있던 부분에서 발생한 것으로 아직 메모리 영역에 대해서 다는 모르지만, 어느 정도는 정리가 되었다.

chatgpt와 추가적인 대화로 상수값은 RAM의 [파이썬 영역]의 [data영역]에서 관리되며 인터프리터 실행 시 미리 메모리 공간을 할당받기 때문에 주소를 가지고 있으므로 직접 참조가 가능하나, 일반 정수는 사용자가 변수에 대입하거나 사용하면 인터프리터가 [data 영역]에서 확인 후 일치하는 값이 없으면 [heap 영역]에서 관리하게 되어 메모리 공간을 할당받는데 인터프리터는 해당 정수를 식별하는게 아닌 사용자가 '이러한 값(-6 이란 값)을 사용하겠다' 라고 선언하기 때문에 해당 값(-6)을 그대로 가져와 메모리 공간을 할당해 준다.(즉, 인터프리터가 값( -6)을 인지하고 공간을 만들기보단 "사용자가 요런거 '-6' 사용하고 싶다는데 공간 좀 마련해보자" 라는 느낌이다.)

[heap 영역]은 private 한 곳으로 해당 값의 주소를 직접 사용할 수 없기 때문에 인터프리터가 변수에 주소를 참조하는 값을 입력한다.

파이썬은 위에서 언급했다시피 대부분 동적 메모리 할당이고, 동적 할당은 [heap 영역]에서 다뤄진다.

이 또한 call by value 가 예외 케이스라고 생각하면 조금 더 편하다.)

 

red_jh : 동적 할당받은 값도 call by value 방법으로 설정해도 메모리 사용에는 문제가 없어 보이는데? 어차피 정수값을 바꾸면 변수에 있는 해당 메모리 주소도 바뀌는 건 동일한 것 같고 문자열도 바꿀 때마다 새로운 공간을 쓸 텐데 별 차이를 모르겠다.

chatgpt : 정수나 문자열을 실제로 그렇게 구현해도 메모리상에는 차이가 없을 순 있으나 해당 설정으로 설정해버리면 예외라는 케이스가 발생하게 되어 파이썬의 일관성이 상실되고, 그로 인해 인터프리터를 다시 인코딩 해야하며 코드가 복잡해지고, 로직도 새로 만들어야 하며 추가적인 메모리를 사용하게 됨으로써 비용이 증가해 결국 유지보수가 어려워게 된다.

 

red_jh: 파이썬의 리스트도 선형 구조라 변수가 리스트의 처음 주소를 call by value 해도 상관없어 보인다.

chatgpt : 그럴 수도 있겠지만 리스트를 call by value 방식으로 하면 변수가 초깃값만 가지기 때문에 리스트가 변할 때마다 변수를 업데이트 해야 하고, 이에 따 메모리를 추가로 사용해야 하는 상황이 발생 할 수 있다.

 

red_jh: 배열은?

chatgpt : 리스트와 마찬가지로 call by value 방식으로 하면 배열의 크기를 바꿀때마다 변수를 업데이트를 해야하고, 이로 인해 메모리를 추가적으로 사용해야 하는 상황이 발생할 수 있다.

 

(위 의문들은 이제 막 공부하는 중이라 기본 내용이 없거나 잘못 인지되어서 생긴 의문일 수도 있으나, 일단 기록해 보고자 기재하였다.)


정리 :  a is -5 = True  와  a is -6 = False  가 다른 이유는 파이썬은 작은 정수(-5 ~ 256)에 한해서 예외적으로 정적 메모리 할당을 받기 때문에 a 가 -5 의 주소값을 직접 활용함으로써 결과가  True  인 것이고, 보통의 정수는 동적 메모리 할당을 받기 때문에 a 가 -6 의 주소값을 직접 활용할 수 없어 파이썬 인터프리터가 주소를 참조하는 값을 a 에게 부여해 주기 때문에 결과가  False  로 나오게 된다.

 

나는 이 내용을 출구 없는 인형 뽑기 기계로 비교하기로 했다.

기계 밖의 인형(작은 정수)은 내가 직접 보고 만지면서 활용할 수 있지만, 기계 안의 인형(일반 정수)은 내가 직접 만질 수 없으니, 기계에 부착된 손(참조하는 값)을 사용해서 만질 수 있게 된다.

 

 

 

 

 

ps. 이제 막 배우는 단계라 오류투성이일 수도 있으니 혹시나 잘못된 정보가 있다면 한 수 부탁드리겠습니다.

반응형

'Python' 카테고리의 다른 글

note 3  (0) 2023.06.18
note 2  (0) 2023.06.17