Categories
del dictionary python

Delete an element from a dictionary

1984

How do I delete an item from a dictionary in Python?

Without modifying the original dictionary, how do I obtain another dict with the item removed?

5

  • 14

    Why do you need a function that returns a dictionary, when you can just modify the dictionary directly?

    May 1, 2011 at 1:26

  • 7

    The dictionary pop method changes the dictionary in-place. Therefore it alters the reference to the dictionary that was passed from the caller to the “helper function”. So the “helper function” doesn’t need to return anything, since the original reference to the dictionary in the caller will already be altered. Don’t assign the return from dict.pop() to anything if you don’t need it. EG: do stuff with my_dict; my_dict.pop(my_key, None); do more stuff with my_dict # now doesn't have my_key. Use deepcopy(my_dict) if needed.

    Jul 1, 2016 at 23:51


  • 1

    Since the original title disagreed with the details and specifically excluded the obvious solution d.pop(), I fixed the title to ask the question specified in the details.

    – smci

    May 14, 2018 at 22:59

  • 1

    We should add a caveat asking if you really want to do this, as if you do it N times on a dictionary with E elements you’ll leak(/use) O(N*E) memory with all the deep copies. If you merely want a read-only (shallow copy), do d.pop(key). But if anything ever modifies the shallow copy, you have a well-known problem with aliasing. It helps if you tell us the wider context. (Is anything else ever modifying the dict values? Are you trying to destructively iterate over a list? if not, what?)

    – smci

    May 15, 2018 at 1:13


  • 7

    “Why do you need a function that returns a dictionary, when you can just modify the dictionary directly?” Perhaps because you want to write pure functions that don’t modify their parameters?

    Jan 7, 2019 at 4:39

2334

The del statement removes an element:

del d[key]

Note that this mutates the existing dictionary, so the contents of the dictionary changes for anybody else who has a reference to the same instance. To return a new dictionary, make a copy of the dictionary:

def removekey(d, key):
    r = dict(d)
    del r[key]
    return r

The dict() constructor makes a shallow copy. To make a deep copy, see the copy module.


Note that making a copy for every dict del/assignment/etc. means you’re going from constant time to linear time, and also using linear space. For small dicts, this is not a problem. But if you’re planning to make lots of copies of large dicts, you probably want a different data structure, like a HAMT (as described in this answer).

12

  • 20

    thats a great point about the mutability of dictionaries +1 – though i can’t think of a time when i wanted copies of the dictionary, i’ve always relied on ‘everyones’ copy being the same. great point.

    – tMC

    Apr 30, 2011 at 21:38

  • 38

    @tMC If you edit the dict as you’re looping through it, it’ll give you an error: RuntimeError: dictionary changed size during iteration

    Aug 29, 2013 at 8:59

  • 22

    What about pop method which in fact does the same? Isn’t it more pythonic? (being dict’s method, not special reserved word)?

    – Serge

    Feb 17, 2014 at 9:48

  • 26

    This answer has a weakness, it could be misleading. Readers may misunderstand that dict(d) can give them a copy with ‘d’. But it’s an incomplete copy. When only doing del keys operations, that’s OK. But when you want to do something else to a nested dict, modifying ‘r’ using that copy method may cause change to the original ‘d’. To get an authentic copy, you need first ‘ import copy ‘, and then ‘r = copy.deepcopy(d) ‘.

    – Zen

    Jul 23, 2014 at 10:34


  • 6

    @GregHewgill, I know that, so it’s not a serious weakness. But since you mentioned “To return a new dictionary, make a copy of the dictionary:”. With your 358K points and 143095 view times, this could be misleading to considerable beginners of python. By the way, I myself was mislead by this post before.

    – Zen

    Jul 24, 2014 at 3:09

461

pop mutates the dictionary.

 >>> lol = {"hello": "gdbye"}
 >>> lol.pop("hello")
     'gdbye'
 >>> lol
     {}

If you want to keep the original you could just copy it.

4

  • 81

    “del” is ok, but “pop” seems more “Pythonic”, in my opinion.

    May 6, 2017 at 2:27

  • 3

    @ivanleoncz why?

    – kevr

    Jan 23, 2018 at 0:45

  • 5

    pop returns the value that was ‘popped’, which allows you to use this value for whatever further reason. If it’s not more “Pythonic”, I’d say that seems better, for sure :). It’s not a dict, but it works the same way for both: github.com/ivanlmj/python-prototypes/blob/master/3.4/…

    Jan 23, 2018 at 0:59


  • 21

    @ivanleoncz It’s also better for one more reason, pop can be provided with a default value that will be returned when a key is missing from dict. It’s good when you need to remove a few keys but some of them might be missing; del would throw KeyError in such case.

    – itachi

    Mar 11, 2020 at 1:56


114

I think your solution is best way to do it. But if you want another solution, you can create a new dictionary with using the keys from old dictionary without including your specified key, like this:

>>> a
{0: 'zero', 1: 'one', 2: 'two', 3: 'three'}
>>> {i:a[i] for i in a if i!=0}
{1: 'one', 2: 'two', 3: 'three'}

5

  • 3

    Really cool. I like the quick method to filter a dictionary without defining a new function.

    – Joe J

    Jul 16, 2013 at 22:15

  • 8

    For those not familiar with comprehensions, you can also do something like this: {i:a[i] for i in a if i not in [0, 1, 2]} if you want to remove several elements.

    – kmatheny

    Feb 4, 2015 at 20:01

  • 27

    Better would be {k:v for k,v in a.items() if k != 0} I think.

    – rlbond

    Feb 13, 2017 at 23:01

  • 1

    The best solution for removing an item by key and returning the result of the new dict in the same line. For example if you need to use an an already constructed dict without a single item as **kwargs, some_function(**{k:v for k,v in some_dict.items() if k not 'some_key'})

    – Cole

    Nov 19, 2017 at 21:14

  • 1

    Best solution here. One liner and it doesn’t mutate the original dictionary.

    May 11, 2018 at 13:52