Was ist besser in Python, Del oder Delattr?

179

Das mag albern sein, aber es hat eine Weile in meinem Gehirn gequält.

Python bietet zwei integrierte Möglichkeiten zum Löschen von Attributen aus Objekten: das Befehlswort del und die integrierte Funktion delattr . Ich bevorzuge delattr, weil es meiner Meinung nach etwas expliziter ist:

del foo.bar
delattr(foo, "bar")

Aber ich frage mich, ob es unter der Haube Unterschiede zwischen ihnen geben könnte.

pydanny
quelle

Antworten:

264

Der erste ist effizienter als der zweite. del foo.barKompiliert zu zwei Bytecode-Anweisungen:

  2           0 LOAD_FAST                0 (foo)
              3 DELETE_ATTR              0 (bar)

während delattr(foo, "bar")dauert fünf:

  2           0 LOAD_GLOBAL              0 (delattr)
              3 LOAD_FAST                0 (foo)
              6 LOAD_CONST               1 ('bar')
              9 CALL_FUNCTION            2
             12 POP_TOP             

Dies führt dazu, dass der erste etwas schneller läuft (aber es ist kein großer Unterschied - 0,15 μs auf meiner Maschine).

Wie die anderen gesagt haben, sollten Sie das zweite Formular wirklich nur verwenden, wenn das zu löschende Attribut dynamisch bestimmt wird.

[Bearbeitet, um die in einer Funktion generierten Bytecode-Anweisungen anzuzeigen, die der Compiler verwenden kann, LOAD_FASTund LOAD_GLOBAL]

Meilen
quelle
6
Mit welchem ​​Tool haben Sie das generiert?
Triptychon
33
Das disModul. Sie können es über die Befehlszeile ausführen python -m disund Code eingeben oder eingeben oder eine Funktion mit zerlegen dis.dis().
Meilen
15
Vorzeitige Optimierung ist die Wurzel allen Übels. ;-) Aber ja, du hast natürlich recht.
Lennart Regebro
26
..so folgt, dass die Liebe zum Geld vorzeitige Optimierung ist?
John Fouhy
5
Vorzeitige Optimierung ist eine Teilmenge der Liebe zum Geld, da dies bedeutet, dass Sie versuchen, weniger für Rechenleistung auszugeben :)
Rob Grant
41
  • del ist expliziter und effizienter;
  • delattr ermöglicht das dynamische Löschen von Attributen.

Betrachten Sie die folgenden Beispiele:

for name in ATTRIBUTES:
    delattr(obj, name)

oder:

def _cleanup(self, name):
    """Do cleanup for an attribute"""
    value = getattr(self, name)
    self._pre_cleanup(name, value)
    delattr(self, name)
    self._post_cleanup(name, value)

Mit del geht das nicht .

Oleksandr Fedorov
quelle
2
Sie können den zweiten mit del machen. del self.__dict__[name], vorausgesetzt natürlich, dass mit der Meta-Klasse kein lustiges Geschäft läuft
smac89
17

Ohne Frage der erstere. Meiner Meinung nach ist das so, als würde man fragen, ob foo.bares besser ist als getattr(foo, "bar")und ich glaube nicht, dass jemand diese Frage stellt :)

Alex Gaynor
quelle
3
Ich bin sicher, es gibt mindestens eine Person da draußen, die getattr (foo, "bar") gegenüber foo.bar vorziehen würde. Zugegeben, ich würde ihnen nicht zustimmen. Aber diese eine Person reicht immer noch aus, um es nicht zweifellos zur ersteren zu machen.
Jason Baker
3
@ Jason Dann ist nichts "zweifellos besser" als alles andere durch Ihre Interpretation des Satzes. Ich denke, dies ist eine völlig vernünftige Verwendung von "zweifellos".
Phob
26
getattr ist vorzuziehen, wenn die Möglichkeit besteht, dass die Eigenschaft nicht vorhanden ist und Sie einen Standardwert festlegen möchten, ohne try / exception-Blöcke schreiben zu müssen. dh. gettattr (foo, "bar", Keine)
Marc Gibbons
2
@MarcGibbons: Warte, das ist eine Sache? Ich habe immer das Muster verwendet if hasattr(obj, 'var') and obj.var == ...... Ich könnte es if getattr(obj, 'var', None) == ...in den meisten Fällen einfach auf reduzieren ! Etwas kürzer und leichter zu lesen, denke ich.
ArtOfWarfare
@ ArtOfWarfare hasattrruft tatsächlich angetattr
Cheniel
14

Es ist wirklich eine Frage der Präferenz, aber die erste ist wahrscheinlich vorzuziehen. Ich würde den zweiten nur verwenden, wenn Sie den Namen des Attributs, das Sie löschen, nicht im Voraus kennen.

Jason Baker
quelle
5

Genau wie getattr und setattr sollte delattr nur verwendet werden, wenn der Attributname unbekannt ist.

In diesem Sinne entspricht es in etwa mehreren Python-Funktionen, mit denen auf integrierte Funktionen auf einer niedrigeren Ebene zugegriffen wird, als Sie normalerweise zur Verfügung haben, z. B. __import__anstelle von importund operator.addanstelle von+

Algorias
quelle
3

Sie sind sich nicht sicher über das Innenleben, aber aus der Sicht der Wiederverwendbarkeit von Code und ohne die Perspektive eines Idioten, verwenden Sie del. Es ist klarer und verständlicher für Leute, die auch aus anderen Sprachen kommen.

eleddy
quelle
1

Wenn Sie der Meinung delattrsind, dass dies expliziter ist, warum dann nicht die getattrganze Zeit anstatt object.attr?

Was unter der Haube angeht ... Ihre Vermutung ist so gut wie meine. Wenn nicht wesentlich besser.

Blutende Finger
quelle
1

Es ist eine alte Frage, aber ich möchte meine 2 Cent einsetzen.

Obwohl del foo.bares eleganter ist, werden Sie manchmal brauchen delattr(foo, "bar"). Wenn Sie beispielsweise über eine interaktive Befehlszeilenschnittstelle verfügen, mit der ein Benutzer ein Element im Objekt durch Eingabe des Namens dynamisch löschen kann, haben Sie keine andere Wahl, als das letztere Formular zu verwenden.

Kaosad
quelle