为什么在不迭代时会出现“'NoneType'不可迭代”错误?

1 投票
3 回答
1934 浏览
提问于 2025-04-17 20:48

当我运行下面的脚本时

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

我本以为输出会是空的(第一个字典不匹配,第二个字典缺少键 '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 个回答

2

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

默认情况下,dict.get 方法在你提供的键不存在时,会返回 None,而 None 不是一个可以遍历的东西,也没有任何方法可以调用。所以,只需给 get 方法多传一个参数,就可以避免返回默认的 None。看看文档里的说明:

D.get(k[,d]) -> 如果 k 在 D 中,返回 D[k],否则返回 d。d 默认是 None。

4

你确实是在进行“迭代”,因为这就是运算符 in 的工作方式。当你写 if 'Bond' not in d.get('b'): 时,Python 会在左边的部分(也就是 d.get('b'))里查找 'Bond'。在第二个条目中,d.get('b') 的值是 None,所以就会出现错误。

你可以给 get 方法传一个第二个参数,这个参数会被当作默认值使用,如果找不到你想要的元素,这样可以简化这个 if 条件:

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

在第二次循环中,d 的值会变成 {'a': 'bonjour monde'},这个字典里没有键 b。所以当你用 d.get('b') 去查找时,它会返回 None,因为 dict.get 方法在找不到指定的键时会返回 None。而 in 操作符会把右边的内容当作一个可迭代的对象来处理。这就是你会遇到这个错误的原因。

你可以简单地这样避免这个问题:

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

撰写回答