Ich kann mir keinen Grund vorstellen, warum Python das del
Schlüsselwort benötigt (und die meisten Sprachen scheinen kein ähnliches Schlüsselwort zu haben). Anstatt beispielsweise eine Variable zu löschen, könnte man None
sie einfach zuweisen . Beim Löschen aus einem Wörterbuch kann eine del
Methode hinzugefügt werden.
Gibt es einen Grund, del
in Python zu bleiben , oder ist es ein Überbleibsel von Pythons Tagen vor der Müllabfuhr?
python
dictionary
python-internals
del
Jason Baker
quelle
quelle
del
.del
ist kein Überbleibsel der Sammlung vor dem Müll, weil man es immer haben könnteused = None
. Es ist einfach immer sinnvoll, eine bestimmte Syntax dafür zu haben. Da wir jetzt zylische GC haben, sind die Fälle, in denen Sie beides verwenden möchten, klein.ERASE
(bestimmte Variablen töten) undCLEAR
( alle Variablen töten )Antworten:
Erstens können Sie neben lokalen Variablen auch andere Dinge löschen
Beides sollte eindeutig nützlich sein. Zweitens
del
macht die Verwendung einer lokalen Variablen die Absicht klarer. Vergleichen Sie:zu
Ich weiß, dass in diesem Fall
del foo
die Absicht besteht, die Variable aus dem Gültigkeitsbereich zu entfernen. Es ist nicht klar, dass das sofoo = None
ist. Wenn jemand gerade zugewiesen hat,foo = None
könnte ich denken, dass es toter Code war. Aber ich weiß sofort, was jemand, der codiert,del foo
versucht hat.quelle
del
in speicherintensiven Berechnungen gesehen, aber als ich es sah, wurde mir sofort klar, warum es notwendig war.del
(da ein Kommentar dasselbe tun könnte, ohne die Sprache zu erweitern), aber ich denke, das ist die beste Antwort.len()
die gleiche Weise können Sie die Funktion auch bestreiten . Wenn dies der Fall ist, wurde die Frage möglicherweise als meinungs- oder sogar geschmacksbezogen geschlossen. Python tendiert einfach dazu, Grundelemente für grundlegende Operationen bereitzustellen, anstatt sich auf Methoden zu verlassen.Es gibt diesen Teil dessen, was
del
funktioniert (aus der Python-Sprachreferenz ):Durch das Zuweisen
None
zu einem Namen wird die Bindung des Namens nicht aus dem Namespace entfernt.(Ich nehme an, es könnte eine Debatte darüber geben, ob das Entfernen einer Namensbindung tatsächlich nützlich ist , aber das ist eine andere Frage.)
quelle
del
eine Namensbindung entfernt wird, da er vorgeschlagen hat, sieNone
als Alternative zuzuweisen .NameError
. Greg Hewgill macht genau diesen Unterschied. Und es ist diese Unterscheidung, die Ihre Behauptung dessen, was das Plakat "klar" verstanden hat, für mich unklar macht.Ein Ort, den ich für
del
nützlich befunden habe, ist das Bereinigen von externen Variablen in for-Schleifen:Jetzt können Sie sicher sein, dass x undefiniert ist, wenn Sie es außerhalb der for-Schleife verwenden.
quelle
del
Zeile hier eingerückt sein (dh Teil der Schleife)?NameError: name 'x' is not defined
wenn die Liste leer ist.Das Löschen einer Variablen unterscheidet sich vom Festlegen auf Keine
Das Löschen von Variablennamen mit
del
wird wahrscheinlich nur selten verwendet, ist jedoch ohne ein Schlüsselwort nicht trivial zu erreichen. Wenn Sie einen Variablennamen durch Schreiben erstellen können,a=1
ist es schön, dass Sie dies theoretisch rückgängig machen können, indem Sie a löschen.In einigen Fällen kann das Debuggen vereinfacht werden, da beim Versuch, auf eine gelöschte Variable zuzugreifen, ein NameError ausgelöst wird.
Sie können Klasseninstanzattribute löschen
Mit Python können Sie Folgendes schreiben:
Wenn Sie einer Klasseninstanz dynamisch Attribute hinzufügen möchten, möchten Sie diese auf jeden Fall durch Schreiben rückgängig machen können
quelle
Es gibt ein spezielles Beispiel dafür, wann Sie eine Ausnahme untersuchen sollten
del
(es kann andere geben, aber ich weiß dies sofort)sys.exc_info()
. Diese Funktion gibt ein Tupel, den Typ der ausgelösten Ausnahme, die Nachricht und einen Traceback zurück.Die ersten beiden Werte reichen normalerweise aus, um einen Fehler zu diagnostizieren und darauf zu reagieren, aber der dritte enthält den gesamten Aufrufstapel zwischen dem Ort, an dem die Ausnahme ausgelöst wurde, und dem Ort, an dem die Ausnahme abgefangen wurde. Insbesondere, wenn Sie so etwas tun
Der Traceback
tb
landet in den Lokalen des Aufrufstapels und erstellt einen Zirkelverweis, der nicht durch Müll gesammelt werden kann. Daher ist es wichtig zu tun:den Zirkelverweis zu brechen. In vielen Fällen , in denen Sie anrufen wollen würde
sys.exc_info()
, wie mit metaclass Magie, die Zurückverfolgungs ist nützlich, so dass Sie sicherstellen müssen , dass Sie es aufzuräumen , bevor Sie möglicherweise die Exception - Handler verlassen können. Wenn Sie den Traceback nicht benötigen, sollten Sie ihn sofort löschen oder einfach Folgendes tun:Um alles zusammen zu vermeiden.
quelle
Nur ein anderes Denken.
Beim Debuggen von http-Anwendungen in einem Framework wie Django kann der Aufrufstapel voller nutzloser und durcheinandergebrachter Variablen, die zuvor verwendet wurden, insbesondere wenn es sich um eine sehr lange Liste handelt, für Entwickler sehr schmerzhaft sein. Daher könnte an dieser Stelle die Namespace-Steuerung nützlich sein.
quelle
Die explizite Verwendung von "del" ist auch besser als das Zuweisen einer Variablen zu None. Wenn Sie versuchen, eine nicht vorhandene Variable zu löschen, wird ein Laufzeitfehler angezeigt. Wenn Sie jedoch versuchen, eine nicht vorhandene Variable auf None zu setzen, setzt Python stillschweigend eine neue Variable auf None, sodass Sie die Variable verlassen wollte gelöscht wo es war. Del hilft Ihnen also, Ihre Fehler früher zu erkennen
quelle
Um den obigen Antworten einige Punkte hinzuzufügen:
del x
Die Definition von
x
zeigt anr -> o
(eine Referenz,r
die auf ein Objekt zeigto
),del x
ändert sich jedochr
eher also
. Es ist eine Operation an der Referenz (dem Zeiger) auf ein Objekt und nicht an dem Objekt, das diesem zugeordnet istx
. Die Unterscheidung zwischenr
undo
ist hier der Schlüssel.locals()
.globals()
wenn esx
dort hingehört .x
hingehört, nicht darauf, wohin esx
zeigt. Die einzige physische Änderung im Gedächtnis ist dies. Wenn es sich beispielsweisex
in einem Wörterbuch oder einer Liste befindet, wird es (als Referenz) von dort entfernt (und nicht unbedingt aus dem Objektpool). In diesem Beispiel ist das Wörterbuch, zu dem es gehört, der Stapelrahmen (locals()
), der sich mit überlapptglobals()
.quelle
Erzwingen Sie das Schließen einer Datei nach Verwendung von numpy.load:
Eine Nischenverwendung vielleicht, aber ich fand es nützlich, wenn
numpy.load
ich eine Datei lese. Hin und wieder aktualisierte ich die Datei und musste eine Datei mit demselben Namen in das Verzeichnis kopieren.Früher habe ich
del
die Datei freigegeben und mir erlaubt, sie in die neue Datei zu kopieren.Hinweis Ich möchte den
with
Kontextmanager vermeiden, da ich mit Plots in der Befehlszeile herumgespielt habe und nicht viel auf die Tabulatortaste drücken wollte!Siehe diese Frage.
quelle
__del__()
Methode für Garbage-Objekte aufgerufen wird oder ob sie überhaupt aufgerufen wird. APIs, die keine andere Möglichkeit bieten, Ressourcen freizugeben, als zu hoffen, dass die__del__()
Methode irgendwann aufgerufen wird (kurz nachdem das Objekt Müll ist), sind bis zu einem gewissen Grad fehlerhaft.del
wird oft in__init__.py
Dateien gesehen. Jede globale Variable, die in einer__init__.py
Datei definiert ist, wird automatisch "exportiert" (sie wird in a aufgenommenfrom module import *
). Eine Möglichkeit, dies zu vermeiden, besteht darin, zu definieren__all__
, aber dies kann chaotisch werden und wird nicht von jedem verwendet.Zum Beispiel, wenn Sie Code in
__init__.py
like hattenDann würde Ihr Modul den
sys
Namen exportieren . Sie sollten stattdessen schreibenquelle
Als Beispiel dafür, wofür
del
verwendet werden kann, finde ich es in Situationen wie diesen nützlich:Diese beiden Funktionen können in verschiedenen Paketen / Module und der Programmierer muss nicht wissen , was Argument Standardwert
c
inf
tatsächlich haben. Wenn Sie also kwargs in Kombination mit del verwenden, können Sie "Ich möchte den Standardwert für c" sagen, indem Sie ihn auf "Keine" setzen (oder in diesem Fall auch belassen).Sie könnten dasselbe mit etwas tun wie:
Allerdings finde ich das vorige Beispiel trockener und eleganter.
quelle
Sie können damit ein einzelnes Element eines Arrays anstelle der Slice-Syntax entfernen
x[i:i+1]=[]
. Dies kann nützlich sein, wenn Sie sich beispielsweise inos.walk
einem Verzeichnis befinden und ein Element im Verzeichnis löschen möchten. Ich würde ein Schlüsselwort dafür jedoch nicht als nützlich erachten, da man einfach eine[].remove(index)
Methode erstellen könnte (die.remove
Methode ist tatsächlich das Suchen und Entfernen der ersten Wertinstanz).quelle
[].pop(index)
und[].remove(item)
. Verwenden Sie keine benannte Variable,"index"
wenn Sie über Wert sprechen, da dies verwirrend wirkt.Ich habe festgestellt
del
, dass es für die pseudo-manuelle Speicherverwaltung nützlich ist, wenn große Datenmengen mit Numpy verarbeitet werden. Zum Beispiel:Dies kann der Unterschied sein, ob ein Skript zum Stillstand gebracht wird, da das System wie verrückt wechselt, wenn der Python GC nicht mithalten kann, und dass es unterhalb einer losen Speicherschwelle, die viel Spielraum für das Surfen auf dem Computer bietet, einwandfrei funktioniert und Code, während es funktioniert.
quelle
Ich denke, einer der Gründe, warum del seine eigene Syntax hat, ist, dass das Ersetzen durch eine Funktion in bestimmten Fällen schwierig sein kann, da es sich um die Bindung oder Variable handelt und nicht um den Wert, auf den es verweist. Wenn also eine Funktionsversion von del erstellt werden soll, muss ein Kontext übergeben werden. Del foo muss zu globals (). Remove ('foo') oder local (). Remove ('foo') werden, was chaotisch wird und weniger lesbar. Trotzdem sage ich, Del loszuwerden wäre gut, da es scheinbar selten verwendet wird. Das Entfernen von Sprachmerkmalen / -fehlern kann jedoch schmerzhaft sein. Vielleicht wird Python 4 es entfernen :)
quelle
Ich möchte auf die akzeptierte Antwort näher eingehen, um die Nuance zwischen dem Setzen einer Variablen
None
und dem Entfernen mitdel
folgenden Variablen hervorzuheben :Gegeben die Variable
foo = 'bar'
und die folgende Funktionsdefinition:Einmal ursprünglich deklariert,
test_var(foo)
ergibt sichvariable tested true
die erwartete Rendite .Versuchen Sie jetzt:
was ergibt
variable tested false
.Vergleichen Sie dieses Verhalten mit:
was jetzt erhöht
NameError: name 'foo' is not defined
.quelle
Noch eine Nischenverwendung: In Pyroot mit ROOT5 oder ROOT6 kann "del" nützlich sein, um ein Python-Objekt zu entfernen, das auf ein nicht mehr vorhandenes C ++ - Objekt verweist. Auf diese Weise kann die dynamische Suche von Pyroot ein C ++ - Objekt mit identischem Namen finden und an den Python-Namen binden. Sie können also ein Szenario haben wie:
Hoffentlich wird diese Nische mit dem saneren Objektmanagement von ROOT7 geschlossen.
quelle
Der Befehl "del" ist sehr nützlich, um Daten in einem Array zu steuern, zum Beispiel:
Ausgabe:
['B', 'C', 'D']
quelle
Einmal musste ich verwenden:
weil nur verwenden:
Die serielle Schnittstelle wurde nicht schnell genug freigegeben, um sie sofort wieder zu öffnen. Aus dieser Lektion habe ich gelernt, dass das
del
wirklich bedeutete: "GC this NOW! Und warte, bis es fertig ist" und das ist in vielen Situationen wirklich nützlich. Natürlich können Sie eine habensystem.gc.del_this_and_wait_balbalbalba(obj)
.quelle
__del__()
es in Python immer falsch ist , sich auf GC zu verlassen und aufzurufen (ich kenne die Gründe für dieses Design jedoch nicht), und es ist besser, die Kontextmanager-API (diewith
Anweisung) zu verwenden.serial
Modul funktioniert auch mit Jython, sodass Ihr Hack dort nicht funktioniert!del ist das Äquivalent von "nicht gesetzt" in vielen Sprachen und als Querverweispunkt, der von einer anderen Sprache zu Python wechselt. Menschen neigen dazu, nach Befehlen zu suchen, die das Gleiche tun, was sie in ihrer ersten Sprache getan haben ... auch Einstellungen Eine Variable auf "" oder keine entfernt die Variable nicht wirklich aus dem Gültigkeitsbereich. Sie leert nur ihren Wert. Der Name der Variable selbst wird immer noch im Speicher gespeichert. Warum?!? in einem speicherintensiven Skript ... Müll hinter seinem Nein-Nein und sowieso ... jede Sprache da draußen hat eine Form einer "nicht gesetzten / gelöschten" var-Funktion ... warum nicht Python?
quelle
del
ruft den Garbage Collector nicht schneller auf als= None
und hinterlässt auf lange Sicht auch keinen Müll. Vielleicht möchten Sie die Garbage Collection von Python verbessern.Jedem Objekt in Python ist ein Bezeichner, ein Typ und ein Referenzzähler zugeordnet. Wenn wir del verwenden, wird der Referenzzähler reduziert. Wenn der Referenzzähler Null wird, ist dies ein potenzieller Kandidat für das Sammeln von Müll. Dies unterscheidet das Del im Vergleich zum Setzen eines Bezeichners auf Keine. In einem späteren Fall bedeutet dies einfach, dass das Objekt einfach wild gelassen wird (bis wir außerhalb des Gültigkeitsbereichs sind, in welchem Fall die Anzahl reduziert wird) und der Bezeichner jetzt einfach auf ein anderes Objekt zeigt (Speicherort).
quelle