当我不迭代时,为什么“'NoneType'不可迭代”错误?

时间:2014-03-04 16:55:30

标签: python iterable

运行以下脚本时

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

我希望输出为空(第一个dict不匹配,第二个缺少键'b')但是我收到错误:

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

我很困惑:为什么我没有迭代(至少在那条线上)会出现argument of type 'NoneType' is not iterable错误?

我确信这是一个明显的错误,但是我看代码越多,我看到的机会就越少:)

3 个答案:

答案 0 :(得分:4)

你确实在迭代,因为这就是运算符in的工作方式。执行:if 'Bond' not in d.get('b'): Python将在左操作数('Bond')内查找d.get('b')。第二个条目中的d.get('b') == None因此是例外。

您可以将第二个参数传递给get,这个参数将被解释为默认值,以便在找不到要缓解此if子句的元素时获取:

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

答案 1 :(得分:2)

使用d.get('b', '')代替d.get('b')

默认情况下dict.get如果您提供的密钥不存在,则返回None,这不是可迭代的或有任何方法可以调用。因此,只需将额外参数传递给get即可避免默认返回值None。请参阅docstring:

  

D.get(k [,d]) - &gt;如果k在D中则为D [k],否则为d。 d默认为无。

答案 2 :(得分:2)

在第二次迭代中,d将为{'a': 'bonjour monde'},其中没有密钥bd.get('b')将返回None,如果找不到密钥,dict.get将返回None。并且in运算符将RHS视为可迭代的。这就是你得到这个错误的原因。

你可以简单地避免这样做,就像这样

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