TypeError:“ NoneType”对象在Python中不可迭代


145

错误TypeError: 'NoneType' object is not iterable是什么意思?

我在以下Python代码上得到它:

def write_file(data, filename): # creates file and writes list to it
  with open(filename, 'wb') as outfile:
    writer = csv.writer(outfile)
    for row in data: # ABOVE ERROR IS THROWN HERE
      writer.writerow(row)

这是我在Python中令人讨厌的失望之一。当None被强制为序列时,它必须产生一个完全无害的空序列。
nehem

7
@nehemiah:Python是强类型的(只是不是静态类型)。None从来没有强迫任何事情。有None默默的行为像其他类型的皮错误; 这 “无害” 相反。如果您需要一个虚假的占位符来表示空序列,则可以使用()''/ "",这两个都是单例并且可以像一样便宜地加载None。如果您希望选择以静默方式将任何虚假的东西视为空序列,则可以这样做for row in data or ():,但是没有人这样做,因为传递None给需要序列的函数是一个错误,不应静默传递。
ShadowRanger

Answers:


203

这表示datais 的值None


37
是的,但是这里的普通场景作者打算完全跳过for循环而不是引发异常。Python的设计在这里有缺陷。当None被视为可迭代时,它必须至少返回空列表。除了让我们插入一些丑陋if data is not None:的处理方式之外,此异常对现实生活中的任何人都没有帮助。
nehem

对于更具体的答案,它可以发生,如果fieldlistDictWriterNone
Arklur

30
试试for i in data or []
BMW

4
@nehemiah:实际上,正确的方法不是检查是否data为is None,而是让异常发生。您希望 API的使用者知道何时使用不正确。接受None为空序列会使诸如的错误mylist = mylist.extend(morestuff)隐藏更长的时间;他们以为自己extend编辑了一个list(并且确实这样做了,但是立即将其替换为None),然后将其传递给OP的函数,并且想知道为什么文件为空,而没有引发任何类型的错误。
ShadowRanger

83

错误说明:“ NoneType”对象不可迭代

在python2中,NoneType是None的类型。在Python3中,NoneType是None的类,例如:

>>> print(type(None))     #Python2
<type 'NoneType'>         #In Python2 the type of None is the 'NoneType' type.

>>> print(type(None))     #Python3
<class 'NoneType'>        #In Python3, the type of None is the 'NoneType' class.

遍历具有值None的变量失败:

for a in None:
    print("k")     #TypeError: 'NoneType' object is not iterable

Python方法如果不返回值,则返回NoneType:

def foo():
    print("k")
a, b = foo()      #TypeError: 'NoneType' object is not iterable

您需要像这样检查NoneType的循环结构:

a = None 
print(a is None)              #prints True
print(a is not None)          #prints False
print(a == None)              #prints True
print(a != None)              #prints False
print(isinstance(a, object))  #prints True
print(isinstance(a, str))     #prints False

Guido说只用于is检查,None因为is它对身份检查更可靠。不要使用相等运算,因为那些运算会加剧自身的泡沫。 Python的编码样式指南-PEP-008

类型是偷偷摸摸的,可以从lambdas偷偷溜走:

import sys
b = lambda x : sys.stdout.write("k") 
for a in b(10): 
    pass            #TypeError: 'NoneType' object is not iterable 

NoneType不是有效的关键字:

a = NoneType     #NameError: name 'NoneType' is not defined

None和字符串的串联:

bar = "something"
foo = None
print foo + bar    #TypeError: cannot concatenate 'str' and 'NoneType' objects

这里发生了什么?

Python的解释器将您的代码转换为pyc字节码。Python虚拟机处理了字节码,它遇到了一个循环结构,该结构表示对包含None的变量进行迭代。通过__iter__在None上调用该方法来执行该操作。

None没有__iter__定义方法,因此Python的虚拟机会告诉您所看到的内容:NoneType没有__iter__方法。

这就是为什么Python的鸭式思维被认为是不好的。程序员使用变量进行了完全合理的操作,在运行时它被None污染,python虚拟机试图继续运行,并在地毯上吐出一堆无关紧要的废话。

Java或C ++没有这些问题,因为不允许您编译此类程序,因为您没有定义发生None时的处理方法。Python允许您执行很多在特殊情况下无法预期的工作,从而为程序员提供了很多上锁的绳索。Python是一个肯定的人,当它像Java和C ++那样阻止您伤害自己时,说是肯定的先生。


2
(a)混乱NoneTypeNone(b)认为NameError: name 'NoneType' is not defined与(c)TypeError: cannot concatenate 'str' and 'NoneType' objects相同,并且TypeError: 'NoneType' object is not iterable(c)Python和Java之间的比较是“一堆无关的废话”
John Machin

3
嗯...如果您传递null给期望任何集合类型的函数,Java都会出现本质上相同的问题。C ++会遇到同样的问题(但通常只会在没有报告原因的情况下死于段错误)nullptr(当然,良好的C ++很少使用指针,但是您所展示的是不良的Python,并且不良的C ++也可能在运行时因null而死亡) 。Python在这里做正确的事;它不是在“继续前进”,而是在您尝试None用于任何None无法执行的操作时出错。您的问题不在于Python,而在于一般的动态类型语言。
ShadowRanger

63

代码:for row in data:
错误消息:TypeError: 'NoneType' object is not iterable

它在抱怨哪个对象?选择两个,rowdata。在中for row in data,哪个需要迭代?只有data

有什么问题data吗?其类型为NoneType。只有None类型NoneType。这样data is None

您可以在IDE中进行验证,也可以通过print "data is", repr(data)for语句之前插入例如并重新运行来进行验证。

考虑下一步需要做什么: 应如何表示“无数据”?我们写一个空文件吗?我们是否引发异常或记录警告或保持沉默?


18

可能产生此错误的另一件事是,当您设置的内容等于从函数返回的值时,却忘记了实际返回任何内容。

例:

def foo(dict_of_dicts):
    for key, row in dict_of_dicts.items():
        for key, inner_row in row.items():
            Do SomeThing
    #Whoops, forgot to return all my stuff

return1, return2, return3 = foo(dict_of_dicts)

这是一个很难发现的错误,因为如果在一次迭代中行变量碰巧为None,那么也会产生该错误。发现它的方法是跟踪在最后一行而不是在函数内部失败。

如果您仅从函数返回一个变量,则不确定是否会产生错误...我怀疑错误“'NoneType'对象在Python中不可迭代”在这种情况下实际上意味着“嘿,我正在尝试遍历返回值以按顺序将它们分配给这三个变量,但我只得到None进行遍历”


1
这正是将我带到这里的原因。那么针对这种情况的Pythonic解决方案是什么?
Dr_Zaszuś

1
好像有一些帮助在这里:stackoverflow.com/questions/1274875/...
Dr_Zaszuś

8

这意味着数据变量正在传递None(类型为NoneType),等效于没有。因此,正如您正在尝试的那样,它不能作为列表进行迭代。


1
如果只是像一个空列表一样进行迭代,那将是一个很好的选择……可以使代码更整洁并减少错误检查
deltanine

4
@deltanine我认为这会使很多问题更难以发现。我很高兴None与空的iterer有所不同。如果您想要描述的行为,请使用for row in data or []:
Mark

7

您正在使用以下参数调用write_file:

write_file(foo, bar)

但是您没有正确定义'foo',或者您的代码中有错字,以便它创建一个新的空变量并将其传入。


1

对我来说,这是戴Groovy帽子而不是Python 3的情况。

returndef函数末尾忘记了关键字。

几个月没有认真编写Python 3。我以为是按照Groovy方式返回例程中评估的最后一条语句。

进行了几次迭代,查看堆栈跟踪,插入try: ... except TypeError: ...块调试/单步执行代码以找出错误所在。

该消息的解决方案当然并没有使错误跳出我的嘴。


谢谢。这正是我的问题。我快要疯了……
J. Brett Cunningham
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.