2016-07-21 18 views
1

Ich schreibe eine Funktion, die ein großes Argument braucht, und läuft für eine lange Zeit. Es braucht das Argument nur zur Hälfte. Gibt es eine Möglichkeit für die Funktion, den Wert zu löschen, auf den das Argument verweist, wenn es keine Referenzen mehr gibt?So löschen Sie ein Funktionsargument frühzeitig?

konnte ich es, sobald die Funktion zurückkehrt, wie diese erhalten gelöscht:

def f(m): 
    print 'S1' 
    m = None 
    #__import__('gc').collect() # Uncommenting this doesn't help. 
    print 'S2' 
class M(object): 
    def __del__(self): 
    print '__del__' 
f(M()) 

Diese Drucke:

S1 
S2 
__del__ 

ich brauche:

S1 
__del__ 
S2 

Ich war auch versuchen def f(*args): und def f(**kwargs), aber es hat nicht geholfen, ich bekomme immer noch __del__ zuletzt.

Bitte beachten Sie, dass mein Code auf der Tatsache basiert, dass Python Referenzzählung hat, und __del__ wird aufgerufen, sobald die Referenzzahl eines Objekts auf Null fällt. Ich möchte, dass der Referenzzähler eines Funktionsarguments in der Mitte einer Funktion auf Null fällt. Ist das möglich?

Bitte beachten Sie, dass ich dieses Problem zu umgehen wissen: eine Liste von Argumenten übergeben:

def f(ms): 
    print 'S1' 
    del ms[:] 
    print 'S2' 
class M(object): 
    def __del__(self): 
    print '__del__' 
f([M()]) 

Diese Drucke:

S1 
__del__ 
S2 

Gibt es eine Möglichkeit die frühe Löschung zu erhalten, ohne die API zu ändern (zB Einführung von Listen zu den Argumenten)?

Wenn es schwierig ist, eine tragbare Lösung zu erhalten, die in vielen Python-Implementierungen funktioniert, ich brauche etwas, die 2.7 in der jüngsten CPython funktioniert. Es muss nicht dokumentiert werden.

+2

Warum wollen Sie das tun wollen? Generell denke ich, dass Python nicht Müll etwas sammeln, sobald es Referenzzählwert Hits 0, aber erst einige Zeit nach (nicht definiert). Sie sollten in der Lage sein, eine Speicherbereinigung zu erzwingen. – syntonym

+1

Das Argument wird in von dem Anrufer Umfang weitergegeben. Letztendlich wird das Objekt dort immer noch referenziert.Wenn Sie die Ref-Anzahl in Ihrer Funktion jedoch so niedrig setzen, dass die Funktion das Objekt beendet, wird wahrscheinlich kein Garbage Collection-Vorgang ausgeführt, da die Referenzen des übergeordneten Bereichs noch nicht bereinigt sind. - Das ist größtenteils nur eine Vermutung, ich weiß nicht, wie sich das Verhalten zwischen 'foo (m)' und 'foo (M()) 'unterscheiden würde; Logik diktiert es * sollte nicht * unterscheiden, aber das ist auch abhängig von der Implementierung. – deceze

+0

Ich * möchte * sagen, dass, selbst wenn Sie das Argument lösen, es noch außerhalb des Funktionsumfangs existiert. –

Antwort

0

Es sieht aus wie es ist nicht möglich, die frühe Löschung in CPython 2.7 zu tun, ohne die API der f Funktion zu ändern.

1

Von the documentation:

CPython Implementierung Detail: CPython nutzt derzeit eine Referenzzählung Schema mit (optional) verzögerte Erkennung von zyklisch verknüpft Müll, die so bald die meisten Objekte sammeln, wie sie unerreichbar werden, ist aber nicht garantiert Müll zu sammeln, der zirkuläre Referenzen enthält. Informationen zur Steuerung der Sammlung von zyklischem Speicher finden Sie in der Dokumentation des GC-Moduls. Andere Implementierungen verhalten sich anders und CPython kann sich ändern. Verlassen Sie sich nicht auf die sofortige Finalisierung von Objekten, wenn sie nicht mehr erreichbar sind (zB: Dateien immer schließen).

Kurz der Modifizierung der Dolmetscher selbst, Sie nicht erreichen, was Sie wollen. __del__ wird aufgerufen, wenn der Dolmetscher, es zu tun entscheidet.

+0

Oder du nennst es selbst. Selbst dann kann der Speicher nicht sofort zurückgewonnen werden, wenn überhaupt. – martineau

+0

Vielen Dank für das Angebot. Es beweist, dass es in CPython keinen dokumentierten und zukunftssicheren Weg dafür gibt. Ich habe die Frage geklärt: Ich würde sogar eine undokumentierte Lösung akzeptieren, die in CPython 2.7 funktioniert. – pts

+0

@martineau: Der Aufruf von 'm .__ del __()' manuell hilft mir nicht. Ich brauche nicht '__del__' aufgerufen zu werden, ich benutze nur' __del__' als Indikator, dass der Python-Interpreter das Objekt löschen möchte. Mir ist wichtig, dass das Objekt frühzeitig gelöscht wird. – pts