Qual è meglio in Python, Del o Delattr?


181

Questo può essere sciocco, ma mi ha tormentato la parte posteriore del cervello per un po '.

Python ci offre due modi integrati per eliminare gli attributi dagli oggetti, la parola del comando del e la funzione integrata delattr . Preferisco delattr perché penso che sia un po 'più esplicito:

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

Ma mi chiedo se potrebbero esserci differenze nascoste tra loro.

Risposte:


266

Il primo è più efficiente del secondo. del foo.barcompila in due istruzioni bytecode:

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

mentre ne delattr(foo, "bar")prende cinque:

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

Questo si traduce nella prima corsa leggermente più veloce (ma non è una differenza enorme - .15 μs sulla mia macchina).

Come hanno detto gli altri, dovresti davvero utilizzare il secondo modulo solo quando l'attributo che stai eliminando viene determinato in modo dinamico.

[Modificato per mostrare le istruzioni bytecode generate all'interno di una funzione, dove il compilatore può usare LOAD_FASTe LOAD_GLOBAL]


6
Quale strumento hai usato per generare questo?
Trittico

33
Il dismodulo. È possibile eseguirlo dalla riga di comando utilizzando python -m dise digitando un codice o disassemblando una funzione con dis.dis().
Miglia,

15
L'ottimizzazione prematura è la radice di tutti i mali. ;-) Ma sì, hai ragione, certo.
Lennart Regebro,

26
..segue quindi che l'amore per il denaro è l'ottimizzazione prematura?
John Fouhy,

5
L'ottimizzazione prematura è un sottoinsieme dell'amore per il denaro, poiché significa che stai cercando di spendere meno per la potenza di elaborazione :)
Rob Grant

41
  • del è più esplicito ed efficiente;
  • delattr consente l'eliminazione dinamica degli attributi.

Considera i seguenti esempi:

for name in ATTRIBUTES:
    delattr(obj, name)

o:

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)

Non puoi farlo con del .


2
Puoi fare il secondo con del. del self.__dict__[name], supponendo ovviamente che non ci siano affari divertenti con la meta classe
smac89

17

Senza dubbio il primo. Dal mio punto di vista, è come chiedere se foo.barè meglio di getattr(foo, "bar"), e non credo che qualcuno stia facendo questa domanda :)


3
Sono sicuro che c'è almeno una persona là fuori che preferirebbe getattr (foo, "bar") rispetto a foo.bar. Certo, non sarei d'accordo con loro. Ma quella persona è ancora abbastanza per renderla indiscutibilmente la prima.
Jason Baker,

3
@Jason Allora niente è "indiscutibilmente migliore" di qualsiasi altra cosa dalla tua interpretazione della frase. Penso che questo sia un uso perfettamente ragionevole di "indiscutibilmente".
Phob,

26
getattr è preferibile quando esiste la possibilità che la proprietà non esista e si desidera impostare un valore predefinito senza dover scrivere i blocchi try / tranne. vale a dire. gettattr (foo, "bar", None)
Marc Gibbons,

2
@MarcGibbons: Aspetta, è una cosa? Ho sempre usato il modello if hasattr(obj, 'var') and obj.var == ...... Potrei semplicemente ridurlo a, if getattr(obj, 'var', None) == ...nella maggior parte dei casi! Penso che sia leggermente più breve e più facile da leggere.
ArtOfWarfare,

@ArtOfWarfare hasattrchiama in realtàgetattr
cheniel,

14

È davvero una questione di preferenza, ma il primo è probabilmente preferibile. Utilizzerei il secondo solo se non conosci il nome dell'attributo che stai eliminando in anticipo.


5

Proprio come getattr e setattr, delattr dovrebbe essere usato solo quando il nome dell'attributo è sconosciuto.

In tal senso, è approssimativamente equivalente a diverse funzionalità di Python utilizzate per accedere alle funzionalità integrate a un livello inferiore a quello normalmente disponibile, come __import__invece di importe operator.addinvece di+


3

Non sono sicuro del funzionamento interno, ma dal punto di vista della riusabilità del codice e non essere una prospettiva da collega idiota, usa del. È più chiaro e compreso da persone provenienti anche da altre lingue.


1

Se pensi che delattrsia più esplicito, allora perché non utilizzarlo getattrsempre anziché object.attr?

Per quanto riguarda il cofano ... la tua ipotesi è buona come la mia. Se non significativamente migliore.


1

È una vecchia domanda, ma vorrei inserire i miei 2 centesimi.

Tuttavia, del foo.barè più elegante, a volte ne avrai bisogno delattr(foo, "bar"). Ad esempio, se si dispone di un'interfaccia a riga di comando interattiva che consente a un utente di eliminare in modo dinamico qualsiasi membro nell'oggetto digitando il nome , non si ha altra scelta che utilizzare quest'ultimo modulo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.