¿Qué es mejor en python, del o delattr?

180

Esto puede ser tonto, pero ha estado molestando la parte posterior de mi cerebro por un tiempo.

Python nos brinda dos formas integradas de eliminar atributos de los objetos, la palabra del comando del y la función integrada delattr . Prefiero delattr porque creo que es un poco más explícito:

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

Pero me pregunto si podría haber diferencias ocultas entre ellos.

pydanny
fuente

Respuestas:

265

El primero es más eficiente que el segundo. del foo.barcompila a dos instrucciones de bytecode:

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

mientras que delattr(foo, "bar")toma cinco:

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

Esto se traduce en la primera ejecución un poco más rápida (pero no es una gran diferencia: 0,15 μs en mi máquina).

Como han dicho los demás, en realidad solo debe usar la segunda forma cuando el atributo que está eliminando se determina dinámicamente.

[Editado para mostrar las instrucciones de bytecode generadas dentro de una función, donde el compilador puede usar LOAD_FASTy LOAD_GLOBAL]

Millas
fuente
66
¿Qué herramienta usaste para generar esto?
Tríptico
33
El dismodulo. Puede ejecutarlo desde la línea de comandos usando python -m disy escribiendo algún código, o desmontar una función con dis.dis().
Miles
15
La optimización prematura es la fuente de todos los males. ;-) Pero sí, tienes razón, por supuesto.
Lennart Regebro
26
¿Entonces se sigue que el amor al dinero es una optimización prematura?
John Fouhy el
55
La optimización prematura es un subconjunto del amor al dinero, ya que significa que estás tratando de gastar menos en potencia de procesamiento :)
Rob Grant
41
  • del es más explícito y eficiente;
  • delattr permite la eliminación dinámica de atributos.

Considere los siguientes ejemplos:

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)

No puedes hacerlo con del .

Oleksandr Fedorov
fuente
2
Puedes hacer el segundo con del. del self.__dict__[name], suponiendo, por supuesto, que no haya asuntos divertidos con la
metaclase
17

Sin lugar a dudas el primero. En mi opinión, esto es como preguntar si foo.bares mejor que getattr(foo, "bar"), y no creo que nadie haga esa pregunta :)

Alex Gaynor
fuente
3
Estoy seguro de que hay al menos una persona que preferiría getattr (foo, "bar") sobre foo.bar. De acuerdo, no estaría de acuerdo con ellos. Pero esa persona todavía es suficiente para que no sea indudablemente la primera.
Jason Baker
3
@ Jason Entonces nada es "indudablemente mejor" que cualquier otra cosa por su interpretación de la frase. Creo que este es un uso perfectamente razonable de "incuestionablemente".
Phob
26
getattr es preferible cuando existe la posibilidad de que la propiedad no exista y desee establecer un valor predeterminado sin tener que escribir bloques try / except. es decir. gettattr (foo, "bar", Ninguno)
Marc Gibbons
2
@MarcGibbons: Espera, ¿eso es una cosa? Siempre he usado el patrón if hasattr(obj, 'var') and obj.var == ...... ¡podría reducir esto a, if getattr(obj, 'var', None) == ...en la mayoría de los casos! Un poco más corto y más fácil de leer, creo.
ArtOfWarfare
@ArtOfWarfare en hasattrrealidad llamagetattr
cheniel
14

Es realmente una cuestión de preferencia, pero la primera es probablemente preferible. Solo usaría el segundo si no conoce el nombre del atributo que está eliminando antes de tiempo.

Jason Baker
fuente
5

Al igual que getattr y setattr, delattr solo debe usarse cuando se desconoce el nombre del atributo.

En ese sentido, es más o menos equivalente a varias características de Python que se utilizan para acceder a la funcionalidad integrada en un nivel inferior al que normalmente tiene disponible, como en __import__lugar de importy en operator.addlugar de+

Algorias
fuente
3

No estoy seguro sobre el funcionamiento interno, pero desde una reutilización de código y no sea una perspectiva de compañero de trabajo, use del. También es más claro y entendido por personas que vienen de otros idiomas.

eleddy
fuente
1

Si crees que delattres más explícito, ¿por qué no usarlo getattrtodo el tiempo en lugar de hacerlo object.attr?

En cuanto a debajo del capó ... su suposición es tan buena como la mía. Si no significativamente mejor.

Dedos sangrantes
fuente
1

Es una vieja pregunta, pero me gustaría poner mis 2 centavos.

Sin embargo, del foo.bares más elegante, a veces lo necesitarás delattr(foo, "bar"). Supongamos que si tiene una interfaz de línea de comandos interactiva que permite a un usuario eliminar dinámicamente cualquier miembro del objeto escribiendo el nombre , entonces no tiene más remedio que usar el último formulario.

kaosad
fuente