문제

나는 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__ 특별한 방법.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top