Frage

Ich bin neu in Python und haben in Swaroop CH „A Byte of Python“ durch die Beispiele gearbeitet. Ich bin ein bestimmtes Verhalten mit der __del__ Methode sehen, die mich ist rätselhaft.

Grundsätzlich, wenn ich das folgende Skript ausführen (in 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')

mit der Python-Konsole (oder den Spyder interaktive Konsole) Ich sehe die folgende:

  
    
      

execfile (U'c: \ 1_eric \ Python \ test1.py ')
      Initializing Swaroop
      Initializing Kalem

             

execfile (U'c: \ 1_eric \ Python \ test1.py ')
      Initializing Swaroop
      Swaroop sagt bye
      Ich bin der letzte
      Initializing Kalem
      Kalem sagt bye
      Ich bin der letzte

    
  

Warum ist die __del__ Methode wird unmittelbar nach dem __init__ auf dem zweiten Lauf genannt?
Ich vermute, dass da die gleichen Instanznamen ( ‚swaroop‘ und ‚Kaleem‘) verwendet werden, dass es die ursprüngliche Instanz freigibt und Müll sammeln sie. Aber, so scheint dies mit der aktuellen Bevölkerungszahl spielte Chaos werden.

Was ist denn hier los?
Was ist ein guter Weg, um diese Art von Verwirrung zu vermeiden?
   Vermeiden Sie den Einsatz von __del__?    Überprüfen Sie, ob vorhandene Instanz Namen, bevor sie wiederverwendet?    ...

Danke, Eric

War es hilfreich?

Lösung

Allgemeine Hinweise: Benutzen Sie nicht __ __ del in Python. Es kann Garbage Collection in einer Reihe von Möglichkeiten, esp brechen. im Fall von zirkulären Verweisen zwischen Objekten.

In Ihrem Beispiel dort ist verschiedene Fragen im Zusammenhang mit der Verwendung von execfile () - das ist keine bewährte Methode - und die Neudefinition der globalen Variablen. By the way, wenn Sie wirklich ein pseudo-destructor (dh ein Code, der aufgerufen wird, wenn das Objekt Müll gesammelt wird) erstellen müssen, schreiben Sie eine so genannte „Finalizerthread“ -Funktion (es ist nicht richtig ein destructor) und rufen Sie es mit WeakRef .ref Rückruf. Es soll nicht eine Instanzmethode natürlich sein, und denken Sie daran, dass Lambda tatsächlich schafft einen Verschluss, daher sicher sein, keinen Hinweis auf Selbst in dem Rückruf zu lecken! Wenn Sie Daten aus dem zerstörten Instanz müssen, verwenden Sie das Argument Ansatz func standardmäßig nur sicher sein, nie , um Referenz ‚Selbst‘ im Inneren des Lambda, sonst wird es nicht funktionieren.

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)

Ausgang (der Schlaf ist da, um Hilfe zu sehen, was passiert):

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

Andere Tipps

Es gibt ein paar Dinge, hier geht. Wenn Ihre Person4 Klasse instanziiert wird, es seine population Klassenvariable auf 0 aus Ihrer interaktiven Konsole initialisiert, erscheinen Sie Ihre „test1.py“ Datei mehrere Male ausgeführt werden. Das zweite Mal, wenn Sie es ausführen, wird die Person4 Klasse wieder erklärt, die es macht technisch andere von dem ersten (obwohl sie den gleichen Namen haben). Das heißt es hat einen eigenen, unabhängigen population zählen.

Nun swaroop und kaleem sind global Variablen, zwischen den beiden Ihre Instanzen "test1.py" geteilt. Python verwendet intern Referenzzählung für die meisten seiner automatischen Speicherbereinigungs, so dass die ursprüngliche Instanz der ersten Klasse Person4 wird erst in der zweiten Zuweisung zu swaroop freigegeben. Zuordnen zu swaroop dekrementiert den Referenzzähler für die erste Instanz, __del__ verursacht genannt zu werden, weil der Referenzzähler jetzt Null ist. Aber weil Sie zu Person4 namentlich innerhalb __del__() Bezug genommen wird, wenn die zurück Instanz verschwindet es verringert die neue Person4.population Zahl, anstelle der alten Person4 Bevölkerungszahl.

Wir hoffen, dass Sinn. Ich kann sehen, warum dies könnte jemand Lernen Python verwirrend sein. Ihre Nutzung von Klassenvariablen zur gleichen Zeit wie die Neudefinition der Person4 Klasse execfile() mit weiter verwirrend Angelegenheiten. Für was es wert ist, habe ich eine Menge von Python-Code geschrieben, und ich glaube nicht, habe ich immer die __del__ spezielle Methode benötigt verwenden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top