2014-03-04 99 views
1

当运行下面的脚本为什么“NoneType”不可迭代“错误,当我不迭代?

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错误,而我不迭代(至少在该行)?

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

回答

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']: 
+0

谢谢。所有响应都很好 - 感谢额外的位(默认值不会有帮助,因为它会匹配'if') – WoJ

+0

@WoJ不,只有默认值不匹配。请让我知道,如果你有不同的理解。 – thefourtheye

+0

如果我在d.get('b',“”)中不使用'if'Bond',那么当'b'不存在时,将返回一个空字符串,它将匹配'if'Bond'不在' - 这不是我想要的(''b''根本不存在,所以测试(从逻辑角度来看)是无效的)。 **你的代码是好的**:i)''b''必须存在以便ii)它被检查为'Bond' – WoJ

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.get('b', ''),而不是d.get('b')

默认情况下dict.get返回None如果您提供的密钥不存在,这不是一个可迭代的或有任何方法调用。所以只需传递一个额外的参数到get以避免默认返回值None。查看文档字符串:

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

相关问题