728x90

cpython 의 경우 가비지 컬렉션은 주로 참조 카운트(reference count)에 기반한다.
refcount 가 0이 되자마자 cpython이 객체의 __del__() 메세드를 호출하고 객체에
할당되어 있는 메모리를 해제함으로써 객체가 제거된다.
파이썬 구현에서는 참조 카운트에 기반하지 않는 더 정교한 가비지 컬렉터를 사용하므로,
객체에 대한 참조가 모두 사라진 경우에도 __del__() 메서드가 바로 호출되지 않을 수도 있다.

 

import weakref
s1 = {1, 2, 3}
s2 = s1


def bye():
    print("Gone with the wind...")


ender = weakref.finalize(s1, bye)
print(ender.alive)
del s1
print(ender.alive)
s2 = "spam"
print(ender.alive)

 

  1. s1과 s2는 동일한 집합 {1, 2, 3}을 가리키는 별명이다.
  2. 이 함수는 제거될 객체의 메서드에 바인딩되거나 제거될 객체를 참조하면 안된다.
  3. s1이 가리키는 객체에 대해 bye() 콜백을 등록한다.
  4. finalize 객체가 호출되기 전의 alive 속성은 참이다.
  5. 앞에서 설명한 대로 del은 객체가 아니라 객체에 대한 참조를 제거한다.
  6. 마지막 참조인 s2를 다른 객체에 바인딩하면 {1, 2, 3} 튜플에 도달할 수 없게 된다.
  7. 튜플이 제거되고, bye() 콜백이 호출되고 ender.alive는 거짓이 된다.

 

del 이 객체를 제거하는 것이 아니고, del을 실행한 후 객체가 도달할 수 없게 된결과로 객체가 제거됨을 명확히 보여준다.
s1 참조가 finalize() 함수에 전달되었고, finalize() 함수는 객체를 감시하고 콜백을 호출하기 위해
객체에 대한 참조를 갖고 있는 것이 아닐까? 이 코드가 작동하는 것은 finalize()가 {1, 2, 3} 튜플 객체에 대한 약한 참조를
가지고 있기 때문이다.

728x90

'Python > python - pythonic' 카테고리의 다른 글

WeakValueDictionary 촌극  (0) 2020.12.04
약한참조  (2) 2020.12.02
간단한 데커레이터 구현하기  (0) 2020.11.28
nonlocal 선언 이 필요한 이유  (0) 2020.11.28
클로저 함수  (0) 2020.11.28