1 minute read

OOP에 대한 수업을 듣다가 의문이 생겼다.

클래스 객체와 인스턴스의 크기는 몇 일까?

아래의 코드를 살펴보자.

# jupyter notebook에서 실행
import sys

# 클래스 생성
class Person():
    def __init__(self, name):
        self.name = name

man = Person("철수")
woman = Person("영희")
print(sys.getsizeof(Person)) ## 1064 출력
print(sys.getsizeof(man)) ## 48 출력
print(sys.getsizeof(woman)) ## 48 출력
            

위와 같은 결과를 얻을 수 있다. 그런데 man.phoneNumber = '01012345678' 과 같이 인스턴스에 새로운 변수를 생성하면 인스턴의 크기가 늘어나지 않을까 궁금해졌다. 결과는 아래와 같다.

man.phoneNumber = '01012345678'
print(sys.getsizeof(man)) ## 48
print(sys.getsizeof(woman)) ## 48

하지만 결과에는 변화가 없다. 그래서 두 가지 가설을 생각해봤다.

  1. man 인스턴스에 48만큼의 공간이 할당되어 있고, 변수가 늘어나면 48의 빈 공간에 할당되다가 일정 시점을 넘어서면 동적으로 man에 더 큰 공간을 할당 한다.

image-20210127144858967

  1. man 인스턴스의 공간, 인스턴스의 변수의 공간이 따로 있다.

image-20210127145122492

그래서 아래의 코드로 확인해보았다.

print(sys.getsizeof(man), id(man)) # 48 2466274840736
print(sys.getsizeof(man.phoneNumber), id(man.phoneNumber)) # 60 2466274952816
print(sys.getsizeof(man.name), id(man.name)) # 78 2466274711568

위의 코드의 결과를 살펴볼 때 2번 가설이 맞는 것 같다.

파이썬의 가비지 컬렉터

그런데 또 한 가지 이상한 점이 발견되었다.

class Dog():
    def __init__(self, name):
        self.name = name
        print(f'{self.name}이 생성되었습니다.')

    def __del__(self):
        print(f'{self.name}가 집을 나갔습니다.')

dog = Dog('choco')
dog = Dog('ggang')

위의 코드를 실행한 결과는 아래와 같다.

choco이 생성되었습니다.
ggang이 생성되었습니다.
choco가 집을 나갔습니다.

choco가 생성된 상태에서 같은 변수명인 dog로 ggang을 생성하면, 언뜻 보기에는 choco가 소멸하고 그 다음에 ggang이 생성되어야 할 것 같은데 그 순서가 반대로 되어있다. 이유가 무엇일까? 이를 이해하기 위해서 아래의 코드를 추가로 살펴봐야한다.

dog = Dog('choco')
print(id(dog))
dog = Dog('ggang')
print(id(dog))

choco이 생성되었습니다.
2027199056768
ggang이 생성되었습니다.
choco가 집을 나갔습니다.
2027199057200

두 dog의 주소는 다르게 나타난다. 이를 이해하기 위해서는 과정을 하나씩 뜯어볼 필요가 있다. 처음 dog 인스턴스가 생성되면 아래 그림과 같이 나타난다.

image-20210127145642755

이 상태에서 dog 변수에 새로운 인스터스를 생성하는 과정을 두 과정으로 쪼갤 수가 있다.

1. ggang 인스턴스가 생성이 된다.
2. dog 변수에 ggang 인스턴스를 할당한다.

이를 다시 그림으로 나타내면, 아래와 같다.

image-20210127145826786

image-20210127145853930

이 과정을 거치고 나면 2027199056768 주소에 할당되어 있던 choco 인스턴스는 변수가 없으니 불러올 방법이 없다. 프로그래머, 프로그램이 사용할 수가 없다는 뜻이다. 이런 메모리가 남아있으면 이를 쓰레기라고 하는 것이다. 이런 것이 한 두개가 아니고 계속 해서 생겨난다면? 메모리 크기는 한정되어있기 때문에 매우 비효율적인 프로그램이 되는 것이다. 그래서 파이썬의 가비지 컬렉터가 이런 쓰레기들을 없애는 것이다. (동적으로 메모리 해제)

제가 아는 선에서 설명을 하여서 잘못된 내용이 있을 수 있습니다. 틀린 부분, 비약이 있는 부분이 있다면 지적 부탁드립니다. 🙏

Tags:

Categories:

Updated: