Quel est le meilleur en python, del ou delattr?

186

C'est peut-être idiot, mais cela me harcèle le dos depuis un moment.

Python nous donne deux méthodes intégrées pour supprimer des attributs d'objets, le mot de commande del et la fonction intégrée delattr . Je préfère delattr car je pense que c'est un peu plus explicite:

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

Mais je me demande s'il pourrait y avoir des différences sous le capot entre eux.

pydanny
la source

Réponses:

273

Le premier est plus efficace que le second. del foo.barse compile en deux instructions bytecode:

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

alors qu'il en delattr(foo, "bar")faut cinq:

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

Cela se traduit par la première exécution légèrement plus rapide (mais ce n'est pas une énorme différence - 0,15 μs sur ma machine).

Comme les autres l'ont dit, vous ne devriez vraiment utiliser le deuxième formulaire que lorsque l'attribut que vous supprimez est déterminé dynamiquement.

[Modifié pour afficher les instructions de bytecode générées dans une fonction, où le compilateur peut utiliser LOAD_FASTet LOAD_GLOBAL]

Miles
la source
6
Quel outil avez-vous utilisé pour générer cela?
Triptyque
33
Le dismodule. Vous pouvez l'exécuter à partir de la ligne de commande en utilisant python -m diset en tapant du code, ou désassembler une fonction avec dis.dis().
Miles
15
L'optimisation prématurée est la racine de tout Mal. ;-) Mais oui, vous avez raison, bien sûr.
Lennart Regebro
26
... il s'ensuit donc que l'amour de l'argent est une optimisation prématurée?
John Fouhy
5
L'optimisation prématurée est un sous-ensemble de l'amour de l'argent, car cela signifie que vous essayez de dépenser moins en puissance de traitement :)
Rob Grant
41
  • del est plus explicite et efficace;
  • delattr permet la suppression dynamique d'attributs.

Considérez les exemples suivants:

for name in ATTRIBUTES:
    delattr(obj, name)

ou:

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)

Vous ne pouvez pas le faire avec del .

Oleksandr Fedorov
la source
2
Vous pouvez faire le second avec del. del self.__dict__[name], en supposant bien sûr qu'aucune affaire amusante ne se passe avec la classe méta
smac89
17

Incontestablement le premier. À mon avis, c'est comme demander si foo.barc'est mieux que getattr(foo, "bar"), et je ne pense pas que quiconque pose cette question :)

Alex Gaynor
la source
3
Je suis sûr qu'il y a au moins une personne qui préférerait getattr (foo, "bar") à foo.bar. Certes, je ne suis pas d'accord avec eux. Mais cette seule personne suffit encore pour en faire sans aucun doute la première.
Jason Baker
3
@Jason Alors rien n'est "incontestablement meilleur" que toute autre chose d'après votre interprétation de la phrase. Je pense que c'est une utilisation parfaitement raisonnable de «sans aucun doute».
Phob
27
getattr est préférable lorsqu'il est possible que la propriété n'existe pas et que vous souhaitez définir une valeur par défaut sans avoir à écrire des blocs try / except. c'est à dire. gettattr (foo, "bar", None)
Marc Gibbons
2
@MarcGibbons: Attendez, c'est une chose? J'ai toujours utilisé le modèle if hasattr(obj, 'var') and obj.var == ...... Je pourrais simplement réduire cela à, if getattr(obj, 'var', None) == ...dans la plupart des cas! Un peu plus court et plus facile à lire, je pense.
ArtOfWarfare
@ArtOfWarfare hasattrappelle réellementgetattr
cheniel
14

C'est vraiment une question de préférence, mais la première est probablement préférable. Je n'utiliserais le second que si vous ne connaissez pas le nom de l'attribut que vous supprimez à l'avance.

Jason Baker
la source
5

Tout comme getattr et setattr, delattr ne doit être utilisé que lorsque le nom d'attribut est inconnu.

En ce sens, cela équivaut à peu près à plusieurs fonctionnalités python utilisées pour accéder aux fonctionnalités intégrées à un niveau inférieur à celui dont vous disposez normalement, par exemple au __import__lieu importet operator.addau lieu de+

Algorias
la source
3

Je ne suis pas sûr du fonctionnement interne, mais du point de vue de la réutilisation du code et ne soyez pas du point de vue d'un collègue, utilisez del. C'est aussi plus clair et compris par les personnes venant d'autres langues.

Eleddy
la source
1

Si vous pensez que delattrc'est plus explicite, alors pourquoi ne pas être utilisé getattrtout le temps plutôt que object.attr?

Quant à sous le capot ... votre estimation est aussi bonne que la mienne. Sinon beaucoup mieux.

Doigts qui saignent
la source
1

C'est une vieille question, mais j'aimerais y mettre mes 2 cents.

Cependant, del foo.barc'est plus élégant, parfois vous en aurez besoin delattr(foo, "bar"). Disons que si vous disposez d'une interface de ligne de commande interactive qui permet à un utilisateur de supprimer dynamiquement n'importe quel membre de l'objet en tapant le nom , vous n'avez pas d'autre choix que d'utiliser ce dernier formulaire.

Kaosad
la source