232

This may be silly, but it's been nagging the back of my brain for a while.

Python gives us two built-in ways to delete attributes from objects, the del command word and the delattr built-in function. I prefer delattr because it I think its a bit more explicit:

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

But I'm wondering if there might be under-the-hood differences between them.

pydanny
  • 7,954
  • 6
  • 34
  • 42

8 Answers8

330

The first is more efficient than the second. del foo.bar compiles to two bytecode instructions:

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

whereas delattr(foo, "bar") takes five:

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

This translates into the first running slightly faster (but it's not a huge difference – .15 μs on my machine).

Like the others have said, you should really only use the second form when the attribute that you're deleting is determined dynamically.

[Edited to show the bytecode instructions generated inside a function, where the compiler can use LOAD_FAST and LOAD_GLOBAL]

Miles
  • 31,360
  • 7
  • 64
  • 74
  • 8
    What tool did you use to generate this? – Kenan Banks Jul 13 '09 at 18:01
  • 45
    The `dis` module. You can run it from the command line using `python -m dis` and typing in some code, or disassemble a function with `dis.dis()`. – Miles Jul 13 '09 at 18:04
  • 18
    Premature optimization is the root of all evil. ;-) But yes, you are right, of course. – Lennart Regebro Jul 13 '09 at 18:24
  • 27
    ..so does it follow that the love of money is premature optimization? – John Fouhy Jul 13 '09 at 22:47
  • 1
    @John Fouhy only if you subscribe to both assertions. But both have stood the test of time. – mike rodent Apr 27 '14 at 08:59
  • 6
    Premature optimization is a subset of the love of money, as it means you're trying to spend less on processing power :) – Rob Grant Feb 24 '15 at 13:31
  • This isn't premature optimization but rather an empirical approach in making a decision as to which approach is better – Mouscellaneous Aug 05 '16 at 13:29
  • 3
    I think it's important to note there are no Python programs where 150 ns will be significant in any way, so the time "efficiency difference" between the two methods should not be the determining factor in which to use. Rather, readability and if you need to pass a string or not should probably be the deciding factor. – user2859458 Jun 15 '17 at 22:29
50
  • del is more explicit and efficient;
  • delattr allows dynamic attribute deleting.

Consider the following examples:

for name in ATTRIBUTES:
    delattr(obj, name)

or:

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)

You can't do it with del.

Oleksandr Fedorov
  • 1,213
  • 10
  • 17
  • 3
    You can do the second one with del. `del self.__dict__[name]`, assuming of course no funny business going on with the meta class – smac89 Mar 01 '18 at 06:51
19

Unquestionably the former. In my view this is like asking whether foo.bar is better than getattr(foo, "bar"), and I don't think anyone is asking that question :)

alex
  • 479,566
  • 201
  • 878
  • 984
Alex Gaynor
  • 14,353
  • 9
  • 63
  • 113
  • 4
    I'm sure there's at least *one* person out there that would prefer getattr(foo, "bar") over foo.bar. Granted, I wouldn't agree with them. But that one person is still enough to make it not unquestionably the former. – Jason Baker Jul 13 '09 at 18:13
  • 3
    @Jason Then nothing is "unquestionably better" than anything else by your interpretation of the phrase. I think this is a perfectly reasonable use of "unquestionably". – Phob May 09 '13 at 21:50
  • 35
    getattr is preferable when there's a possibility that the property does not exist and you wish to set a default value without having to write try/except blocks. ie. gettattr(foo, "bar", None) – Marc Gibbons Sep 04 '13 at 15:09
  • 3
    @MarcGibbons: Wait, that's a thing? I've always used the pattern `if hasattr(obj, 'var') and obj.var == ...`... I could just reduce this to, `if getattr(obj, 'var', None) == ...` in most cases! Slightly shorter and easier to read, I think. – ArtOfWarfare Apr 20 '15 at 17:53
  • @ArtOfWarfare `hasattr` actually calls `getattr` – cheniel May 12 '17 at 20:04
16

It's really a matter of preference, but the first is probably preferable. I'd only use the second one if you don't know the name of the attribute that you're deleting ahead of time.

Jason Baker
  • 192,085
  • 135
  • 376
  • 510
6

Just like getattr and setattr, delattr should only be used when the attribute name is unknown.

In that sense, it's roughly equivalent to several python features that are used to access built-in functionality at a lower level than you normally have available, such as __import__ instead of import and operator.add instead of +

Algorias
  • 3,043
  • 5
  • 22
  • 16
3

Not sure about the inner workings, but from a code reusability and don't be a jerk coworker perspective, use del. It's more clear and understood by people coming from other languages as well.

eleddy
  • 1,354
  • 2
  • 9
  • 8
3

It is an old question, but I would like to put my 2 cents in.

Though, del foo.bar is more elegant, at times you will need delattr(foo, "bar"). Say, if you have an interactive command line interface that allows a user to dynamically delete any member in the object by typing the name, then you have no choice but to use the latter form.

kaosad
  • 1,233
  • 1
  • 11
  • 15
2

If you think delattr is more explicit, then why not used getattr all the time rather than object.attr?

As for under the hood... your guess is as good as mine. If not significantly better.

Bleeding Fingers
  • 6,993
  • 7
  • 46
  • 74