107

If the value is None, I'd like to change it to "" (empty string).

I start off like this, but I forget:

for k, v in mydict.items():
    if v is None:
... right?
TIMEX
  • 259,804
  • 351
  • 777
  • 1,080

3 Answers3

180
for k, v in mydict.iteritems():
    if v is None:
        mydict[k] = ''

In a more general case, e.g. if you were adding or removing keys, it might not be safe to change the structure of the container you're looping on -- so using items to loop on an independent list copy thereof might be prudent -- but assigning a different value at a given existing index does not incur any problem, so, in Python 2.any, it's better to use iteritems.

In Python3 however the code gives AttributeError: 'dict' object has no attribute 'iteritems' error. Use items() instead of iteritems() here.

Refer to this post.

Community
  • 1
  • 1
Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
  • 1
    @John, it applies to _any_ built-in **container** -- just as much to a list as to a dict -- and I think "index" is a more generic term than "key". – Alex Martelli Feb 23 '10 at 02:10
  • 2
    `mydict[k] = ''` -- your example updates `k` index to an immutable object, `''`. So after this, `k` would point to an entirely different object than `v`. Would this mutate the `k` index in some way that might cause problems with `.iteritems()`? – CivFan Apr 14 '15 at 18:28
  • 4
    @CivFan, nope, altering or re-assigning a **value** (as opposed to a **key**) does not give problems with `dict.iteritems`. – Alex Martelli Apr 17 '15 at 10:46
  • 1
    Hmm ... I wonder if the advice to use `.items` to loop if you're adding/removing keys is prudent. I don't know the implementation details of `dict_items` objects, but it seems that you might still have issues [iterating over them in python3.x](https://docs.python.org/3.4/library/stdtypes.html#dictionary-view-objects) if you're adding/deleting keys. In that case, it's probably safest to iterate over a list of the keys: `for k in list(mydict): v = mydict[k]; ...` – mgilson May 07 '15 at 19:04
17

You could create a dict comprehension of just the elements whose values are None, and then update back into the original:

tmp = dict((k,"") for k,v in mydict.iteritems() if v is None)
mydict.update(tmp)

Update - did some performance tests

Well, after trying dicts of from 100 to 10,000 items, with varying percentage of None values, the performance of Alex's solution is across-the-board about twice as fast as this solution.

PaulMcG
  • 62,419
  • 16
  • 94
  • 130
  • Hmm, for Python 2.7 I see about the same performance ( though the Alex's method is still always faster ) ; I have tried dicts with 1000 .. 100000 values and None percentage from 2 to 50 %% ; for comparison, the method from [buckley](http://stackoverflow.com/a/2315545/558008) ( with s/items/iteritems/ ) was about 4 times slower. I think this is kind of interesting, since your form allows one to alter the dictionary on iteration. – ジョージ Jul 03 '14 at 10:52
  • list comprehensions make a new dict, that's why it is slower as compared to the accepted answer. – Muhammad Khuzaima Umair Jul 08 '22 at 05:30
14

Comprehensions are usually faster, and this has the advantage of not editing mydict during the iteration:

mydict = dict((k, v if v else '') for k, v in mydict.items())
Noctis Skytower
  • 21,433
  • 16
  • 79
  • 117
buckley
  • 2,060
  • 1
  • 17
  • 12
  • 1
    If you are using `.items()` it doesn't matter (for python2) if you modify `mydict` as the list that `.items()` returns will not change even if you add/remove keys of `mydict` – John La Rooy Feb 23 '10 at 01:30
  • 4
    Changing only values in a dict is never a problem; grief is caused by adding/deleting KEYS while iterating over the dict. Comprehensions are faster than WHAT? Really fast: copying the whole dict when there's one or two Nones to change. Speaking of Nones, you should have `if v is not None` instead of `if v` (re-read the question). Overall summary: -1 – John Machin Feb 23 '10 at 02:06
  • Your solution replaces 0, empty list and everything that is False in a boolean context by `''`. I would suggest replacing `if v` by `if v is None`, this is also more PEP 8 compliant : https://www.python.org/dev/peps/pep-0008/#programming-recommendations – Statistic Dean Jan 11 '19 at 09:33