Question

When running the following script

dictlist = [
    {'a': 'hello world', 'b': 'my name is Bond'},
    {'a': 'bonjour monde'}
]

for d in dictlist:
    if 'Bond' not in d.get('b'):
        print d

I expected the output to be empty (the first dict does no match, the second one is missing the key 'b') but I get the error:

Traceback (most recent call last):
  File "C:/dev/mytest.py", line 7, in <module>
    if 'Bond' not in d.get('b'):
TypeError: argument of type 'NoneType' is not iterable

I am confused: why is there a argument of type 'NoneType' is not iterable error while I am not iterating (at least on that line)?

I am sure this is an obvious error but the more I look at the code, the less chances that I see it :)

Was it helpful?

Solution 2

In the second iteration, d will be {'a': 'bonjour monde'}, which doesn't have the key b. d.get('b') will return None as dict.get will return None if the key is not found. And in operator treats the RHS as an iterable. That is why you are getting this error.

You can simply avoid that, like this

for d in dictlist:
    if 'b' in d and 'Bond' not in d['b']:

OTHER TIPS

You are indeed iterating since that's the way operator in works. When you do: if 'Bond' not in d.get('b'): Python will look for 'Bond' inside the left operand (d.get('b')). d.get('b') == None in the second entry hence the exception.

You can pass a second argument to get which would be interpreted as the default value to get in case of not finding the element to ease this if clause:

if 'Bond' not in d.get('b',[]):

Use d.get('b', '') instead of d.get('b').

By default dict.get returns None if the key you provide does not exist, which is not an iterable or has any method to call. So simply pass an extra argument to get to avoid the default return value None. See the docstring:

D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top