__del__ 방법이 예상되지 않을 때 파이썬에서 호출되는 방법
-
20-09-2019 - |
문제
나는 Python을 처음 접했고 Swaroop Ch의 "A Python의 바이트"의 예제를 통해 작업하고 있습니다. 나는 어떤 행동을보고있다 __del__
나를 당혹스럽게하는 방법.
기본적으로 다음 스크립트를 실행하면 (Python 2.6.2)
class Person4:
'''Represents a person'''
population = 0
def __init__(self, name):
'''Initialize the person's data'''
self.name = name
print 'Initializing %s'% self.name
#When the person is created they increase the population
Person4.population += 1
def __del__(self):
'''I am dying'''
print '%s says bye' % self.name
Person4.population -= 1
if Person4.population == 0:
print 'I am the last one'
else:
print 'There are still %d left' % Person4.population
swaroop = Person4('Swaroop')
kaleem = Person4('Kalem')
Python 콘솔 (또는 Spyder Interactive Console)을 사용하여 다음을 볼 수 있습니다.
execfile (u'c : 1_ic python test1.py ')
Swaroop 초기화
칼렘 초기화execfile (u'c : 1_ic python test1.py ')
Swaroop 초기화
Swaroop은 작별 인사를 말합니다
나는 마지막 사람입니다
칼렘 초기화
칼렘은 작별 인사를 말한다
나는 마지막 사람입니다
왜 __del__
방법은 즉시 호출됩니다 __init__
두 번째 달리기에서?
동일한 인스턴스 이름 ( 'swaroop'및 'kaleem')이 원래 인스턴스를 공개하고 쓰레기를 수집하는 것을 사용하고 있다고 생각합니다. 그러나 이것은 현재 인구 수와 혼란을 겪고있는 것 같습니다.
여기서 무슨 일이 일어나고 있습니까?
이런 종류의 혼란을 피하는 좋은 방법은 무엇입니까?
사용을 피하십시오 __del__
? 기존 인스턴스 이름을 재사용하기 전에 확인 하시겠습니까? ...
감사합니다, 에릭
해결책
일반적인 조언 : 파이썬에서 __ del __을 사용하지 마십시오. 여러 가지 방법으로 쓰레기 수집을 깰 수 있습니다. 객체 사이의 원형 참조의 경우.
예에서는 Execfile ()의 사용과 관련된 다양한 문제가 있으며, 이는 모범 사례가 아닌 글로벌 변수의 재정의입니다. 그건 그렇고, 실제로 의사 파괴자를 만들어야한다면 (즉, 물체가 수집 될 때마다 호출되는 코드), 소위 "Finalizer"기능을 작성하고 (적절하게 파괴자가 아님) 약점을 사용하여 호출하십시오. .ref 콜백. 물론 인스턴스 방법이되어서는 안되며 Lambda는 실제로 폐쇄를 생성한다는 것을 기억하십시오. 따라서 콜백에서 자기 자신에 대한 언급을 유출하지 않아야합니다! 파괴 된 인스턴스의 데이터가 필요한 경우 FUNC 기본 인수 접근 방식을 사용하십시오. 절대 람다 내부에서 '자기'를 언급하려면 그렇지 않으면 작동하지 않습니다.
from weakref import ref
from time import sleep
class Person4:
'''Represents a person'''
population = 0
def __init__(self, name):
'''Initialize the person's data'''
self.name = name
print 'Initializing %s'% self.name
#When the person is created they increase the population
Person4.population += 1
self._wr = ref(self, lambda wr, name=self.name: Person4_finalizer(name))
def Person4_finalizer(name):
'''I am dying'''
print '%s says bye' % name
Person4.population -= 1
if Person4.population == 0:
print 'I am the last one'
else:
print 'There are still %d left' % Person4.population
p1 = Person4("one")
p2 = Person4("two")
p3 = Person4("three")
del p2
del p3
sleep(5)
생산량 (수면은 무슨 일이 일어나고 있는지 확인하는 데 도움이됩니다) :
Initializing one
Initializing two
Initializing three
two says bye
There are still 2 left
three says bye
There are still 1 left
one says bye
I am the last one
다른 팁
여기에는 몇 가지 일이 있습니다. 당신의 Person4
클래스는 인스턴스화되며 초기화됩니다 population
대화식 콘솔에서 "test1.py"파일을 여러 번 실행하는 것으로 보입니다. 두 번째로 당신이 그것을 실행할 때 Person4
수업은 다시 선언되어 기술적으로 만들어집니다 다른 첫 번째로부터 (동일한 이름을 가지고 있지만). 그것은 그것이 독립적 인 것을 의미합니다 population
세다.
지금, swaroop
그리고 kaleem
~이다 글로벌 "test1.py"의 두 인스턴스간에 공유되는 변수. 파이썬은 내부적으로 대부분의 자동 쓰레기 수집에 대한 참조 계산을 사용하므로 첫 번째 원래 인스턴스 Person4
클래스는 두 번째 과제까지 공개되지 않습니다 swaroop
. 할당 swaroop
첫 번째 인스턴스의 기준 수를 감소시켜 __del__
참조 수가 이제 0이기 때문에 호출됩니다. 그러나 당신이 언급하기 때문에 Person4
내부 이름으로 __del__()
, 때 이전 인스턴스가 사라집니다 새로운 Person4.population
오래된 대신에 계산하십시오 Person4
인구 수.
잘만되면 그것은 말이되었습니다. 왜 이것이 왜 파이썬을 배우는 사람에게 혼란 스러울 수 있는지 알 수 있습니다. 재정의하는 것과 동시에 클래스 변수 사용 Person4
사용 수업 execfile()
더 혼란스러운 문제입니다. 가치가있는 것에 대해, 나는 많은 파이썬 코드를 작성했는데 나는 사용해야한다고 생각하지 않습니다. __del__
특별한 방법.