[python] __del__ 메서드는 무엇이며 어떻게 호출합니까?

코드를 읽고 있습니다. __del__메소드가 정의 된 클래스가 있습니다 . 이 메서드가 클래스의 인스턴스를 파괴하는 데 사용된다는 것을 알아 냈습니다. 그러나이 방법이 사용되는 곳을 찾을 수 없습니다. 그 주된 이유는이 방법이 어떻게 사용되는지 모르기 때문입니다 obj1.del(). 그래서, 내 질문은 __del__메서드 를 호출하는 방법입니다.



답변

__del__A는 파이널 라이저는 . 객체에 대한 모든 참조가 삭제 된 후 어느 시점에서 발생 하는 객체가 가비지 수집 될 때 호출 됩니다.

A의 간단한 경우 이것은 당신이 말하는 직후가 될 수 del x있는 경우, 또는 x함수 종료 후, 지역 변수입니다. 특히 순환 참조가없는 한 CPython (표준 Python 구현)은 즉시 가비지 수집합니다.

그러나 이것은 CPython 의 구현 세부 사항 입니다. 유일한 요구 파이썬 가비지 컬렉션의 속성은 그런 일이 있다는 것입니다 모든 참조가 삭제 된 필요하지 않습니다이 힘이 발생하므로 직후전혀 발생하지 않을 수 있습니다 .

더욱, 변수에 대해 오랫동안 살 수 많은 이유 , 예를 들면 전파 예외 나 또한 0보다 변수 참조 카운트 이상을 유지할 수 있습니다 모듈 성찰은, 변수의 일부가 될 수 있습니다 참조주기 – CPython의 쓰레기 수거와 휴식 대부분 켜져 , 전부는 아니지만 그러한주기는 물론 주기적으로 만 발생합니다.

실행을 보장 할 수 없기 때문에 실행 해야하는 코드를 입력 해서는 안됩니다.__del__() 대신이 코드는 블록의 finally절이나 명령문 try의 컨텍스트 관리자에 속합니다 with. 그러나 다음과 같은 유효한 사용 사례 가 있습니다 __del__. 예를 들어 객체가 X참조 Y사본을 Y전역 cache( cache['X -> Y'] = Y) 에 참조하고 보관하는 X.__del__경우 캐시 항목도 삭제하는 것이 정중합니다 .

소멸자가 (위의 지침을 위반하여) 필요한 정리를 제공한다는 것을 알고 있다면 , 메서드로서 특별한 것이 없기 때문에 직접 호출 할 수 있습니다 : x.__del__(). 분명히 두 번 전화해도 괜찮다는 것을 알고있는 경우에만 그렇게해야합니다. 또는 최후의 수단으로 다음을 사용하여이 방법을 재정의 할 수 있습니다.

type(x).__del__ = my_safe_cleanup_method  


답변

더 정확한 질문이지만 다른 질문에 대한 답변을 작성했습니다.

생성자와 소멸자는 어떻게 작동합니까?

여기에 약간의 의견이있는 답변이 있습니다.

사용하지 마십시오 __del__. 이것은 C ++ 또는 소멸자를 위해 만들어진 언어가 아닙니다. 이 __del__메서드는 실제로 Python 3.x에서 사라져야하지만 누군가 의미있는 사용 사례를 찾을 수있을 것이라고 확신합니다. 을 사용해야하는 경우 http://docs.python.org/reference/datamodel.html__del__ 의 기본 제한 사항에 유의 하세요.

  • __del__가비지 수집기가 객체를 수집 할 때 호출됩니다. 객체에 대한 마지막 참조를 잃었을 때가 아니라 del object.
  • __del____del__MRO (메서드 확인 순서)인지 아니면 각 슈퍼 클래스 만 호출하는지는 확실하지 않지만 수퍼 클래스에서 임의의 호출을 담당합니다 .
  • 갖는 __del__가비지 수집기가 검출하고, 링크리스트에 마지막 참조 손실 같은 환상 링크 청소 포기한다는 수단. gc.garbage에서 무시 된 객체 목록을 가져올 수 있습니다. 때때로 약한 참조를 사용하여 순환을 완전히 피할 수 있습니다. 이것은 때때로 논쟁이되고 있습니다 : http://mail.python.org/pipermail/python-ideas/2009-October/006194.html 참조 .
  • __del__함수는 속이고, 객체에 대한 참조를 저장하고, 가비지 수집을 중지 할 수 있습니다.
  • 명시 적으로 발생한 예외 __del__는 무시됩니다.
  • __del__보완 __new__보다 훨씬 더 __init__. 이것은 혼란스러워집니다. 설명 및 문제는 http://www.algorithm.co.il/blogs/programming/python-gotchas-1- del -is-not-the-opposite-of- init / 를 참조 하십시오 .
  • __del__파이썬에서 “잘 사랑받는”아이가 아닙니다. sys.exit () 문서는 나가기 전에 가비지 수집 여부를 지정하지 않으며 많은 이상한 문제가 있음을 알 수 있습니다. __del__on globals를 호출 하면 이상한 순서 문제가 발생합니다 (예 : http://bugs.python.org/issue5099) . 실패 __del__하더라도 호출 해야합니까 __init__? 긴 스레드에 대해서는 http://mail.python.org/pipermail/python-dev/2000-March/thread.html#2423 을 참조 하십시오 .

그러나 다른 한편으로는:

그리고 그 __del__기능이 마음에 들지 않는 비정상적인 이유 .

  • 누군가가 __del__그것을 가져올 때마다 30 개의 혼란 메시지로 이어집니다.
  • Zen of Python에서 다음 항목을 중단합니다.
    • 단순한 것이 복잡한 것보다 낫습니다.
    • 특별한 경우는 규칙을 어길만큼 특별하지 않습니다.
    • 오류는 조용히 전달되지 않아야합니다.
    • 모호함에도 불구하고 추측하려는 유혹을 거부하십시오.
    • 이를 수행하는 확실한 방법은 하나, 그리고 바람직하게는 하나만 있어야합니다.
    • 구현이 설명하기 어렵다면 그것은 나쁜 생각입니다.

따라서 사용하지 않는 이유를 찾으십시오 __del__.


답변

__del__객체가 쓰레기 수집 때 방법, 그것은 호출됩니다. 하지만 반드시 호출이 보장되는 것은 아닙니다. 다음 코드는 그 자체로이를 수행 할 필요는 없습니다.

del obj

그 이유 del는 참조 횟수를 1만큼 감소시키기 때문 입니다. 다른 것이 객체에 대한 참조를 가지고 있으면 __del__호출되지 않습니다.

__del__하지만 사용에 대한 몇 가지주의 사항이 있습니다 . 일반적으로 그들은 일반적으로 그다지 유용하지 않습니다. close 메소드 또는 with 문 을 사용하고 싶은 것처럼 들립니다 .

메소드 __del__ 대한 파이썬 문서를 참조하십시오 .

주의해야 할 또 다른 사항 : __del__메소드가 과도하게 사용되면 가비지 수집을 금지 할 수 있습니다. 특히 __del__메서드가 있는 개체가 두 개 이상있는 순환 참조는 가비지 수집되지 않습니다. 가비지 수집기가 먼저 호출 할 항목을 알지 못하기 때문입니다. 자세한 정보 는 gc 모듈에 대한 문서를 참조하십시오 .


답변

__del__메서드 (맞춤법에주의하세요!)는 객체가 마침내 파괴 될 때 호출됩니다. 기술적으로 말하면 (cPython에서) 객체에 대한 참조가 더 이상 없을 때, 즉 범위를 벗어날 때입니다.

객체를 삭제하고 __del__메서드 를 호출 하려면

del obj1

객체를 삭제합니다 (다른 참조가없는 경우).

이런 작은 수업을 작성하는 것이 좋습니다

class T:
    def __del__(self):
        print "deleted"

그리고 파이썬 인터프리터에서 조사하십시오.

>>> a = T()
>>> del a
deleted
>>> a = T()
>>> b = a
>>> del b
>>> del a
deleted
>>> def fn():
...     a = T()
...     print "exiting fn"
...
>>> fn()
exiting fn
deleted
>>>   

jython과 ironpython은 객체가 정확히 언제 삭제되고 __del__호출 되는지에 대한 규칙이 다릅니다 . __del__이것과 객체와 그 환경이 호출 될 때 알 수없는 상태에있을 수 있다는 사실 때문에 사용하는 것은 좋은 습관으로 간주되지 않습니다 . 절대적 __del__으로 호출 될 것이라는 보장은 없습니다 . 인터프리터는 모든 객체를 삭제하지 않고 다양한 방법으로 종료 할 수 있습니다.


답변

앞서 언급했듯이 __del__기능은 다소 불안정합니다. 유용 해 보일 수있는 경우 대신 __enter____exit__메서드를 사용하는 것이 좋습니다. 이것은 with open() as f: pass파일 액세스에 사용되는 구문 과 유사한 동작을 제공 합니다. __enter__범위에 진입 할 때 자동으로 호출 with동안 __exit__그것을 종료 할 때 자동으로 호출된다. 자세한 내용은 이 질문 을 참조하십시오.


답변