2009-07-13 14 views
125

Questo potrebbe essere sciocco, ma mi ha tormentato la parte posteriore del cervello per un po '.Quale è meglio in python, del o delattr?

Python ci dà due built-in modi per cancellare gli attributi dagli oggetti, il del parola di comando e la funzione built-in delattr. Io preferisco delattr perché penso che sia un po 'più esplicito:

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

ma mi chiedo se ci potrebbe essere sotto il cofano differenze tra di loro.

risposta

201

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

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

mentre 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 esecuzione leggermente più veloce (ma non è una differenza enorme - .15 ms sulla mia macchina).

Come gli altri hanno già detto, dovresti davvero usare solo il secondo modulo quando l'attributo che stai cancellando è determinato dinamicamente.

[A cura di mostrare le istruzioni bytecode generato all'interno di una funzione, in cui il compilatore può utilizzare LOAD_FAST e LOAD_GLOBAL]

+4

Quale strumento hai usato per generare questo? – Triptych

+25

Il modulo 'dis'. Puoi eseguirlo dalla riga di comando usando 'python -m dis' e digitando un codice, o disassemblando una funzione con' dis.dis() '. – Miles

+14

L'ottimizzazione prematura è la radice di tutto il male. ;-) Ma sì, hai ragione, certo. –

14

È davvero una questione di preferenza, ma il primo è probabilmente preferibile. Userò solo il secondo se non conosci il nome dell'attributo che stai cancellando prima del tempo.

16

Indiscutibilmente 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 ci sia almeno * una * persona là fuori che preferire getattr (foo, "barra") su foo.bar. Concesso, non sarei d'accordo con loro. Ma quell'unica persona è ancora abbastanza da renderla non indiscutibilmente la prima. –

+2

@Jason Quindi niente è "indiscutibilmente meglio" di qualsiasi altra cosa dalla tua interpretazione della frase. Penso che questo sia un uso perfettamente ragionevole di "indiscutibilmente". – Phob

+21

getattr è preferibile quando esiste la possibilità che la proprietà non esista e si desideri impostare un valore predefinito senza dover scrivere try/except blocks. ie. gettattr (foo, "bar", None) –

0

Se si pensa delattr è più esplicito, allora perché non utilizzato getattr tutto il tempo, piuttosto che object.attr?

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

5

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

In questo senso, è più o meno equivalente a diverse funzioni Python che vengono utilizzati per accedere alle funzionalità built-in ad un livello inferiore a quello che normalmente si ha a disposizione, come ad esempio __import__ invece di import e operator.add invece di +

3
Non

sicuro del funzionamento interno, ma da una riutilizzabilità del codice e non essere una prospettiva da coworker, usa del. È più chiaro e comprensibile anche da persone provenienti da altre lingue.

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

considerare 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.

+0

Puoi fare il secondo con del. 'del self .__ dict __ [nome]', presupponendo ovviamente che non ci siano affari divertenti in corso con la meta classe – smac89

1

Si tratta di una vecchia questione, ma vorrei mettere i miei 2 centesimi.

Anche se, del foo.bar è più elegante, a volte è necessario delattr(foo, "bar"). Supponiamo, 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 tramite digitando il nome, quindi non si ha altra scelta che utilizzare quest'ultimo modulo.

Problemi correlati