类型错误:'NoneType'对象不可迭代

209

TypeError: 'NoneType' object is not iterable是什么意思? 例如:

for row in data:  # Gives TypeError!
    print(row)

4
这是我在Python中感到非常失望的问题之一。当将None强制转换为序列时,它应该产生一个空序列,完全没有危害。 - nehem
11
Python是强类型语言(只不过不是静态类型),None永远不会被强制转换成任何类型。让None像其他类型一样悄无声息地执行会隐藏错误,这恰好与“无害”相反。如果你需要一个代表空序列的falsy占位符,可以使用()''/"",它们都是单例并且可以像None一样廉价地加载。如果想要将任何falsy值默认视为空序列,可以使用for row in data or ():,但没人这样做,因为将None传递给期望序列的函数会产生错误,不应该悄悄地通过。 - ShadowRanger
2
@nehem 你一定是JavaScript的粉丝。 - Matt Yoon
@MattYoon JS 做得很好。 - nehem
@ShadowRanger,这是一个很糟糕的借口。如果str可以被视为可迭代对象,那么将None强制转换为空迭代对象有什么问题,特别是在意图明确的情况下。更糟糕的是,列表和字典可以被强制转换为布尔值,甚至字符串也可以。强类型对于布尔值并没有很好地保持。 - nehem
显示剩余3条评论
13个回答

264

这意味着data的值是None


68
正确,但是作者想要表达的常见情况是完全跳过for循环而不是引发异常。Python在这里的设计存在缺陷。当将None视为可迭代对象时,它至少必须返回一个空列表。这个异常在现实生活中从来没有帮助过任何人,除了让我们插入一些丑陋的处理方式,比如if data is not None: - nehem
为了得到更具体的答案,如果DictWriterfieldlistNone,就会发生这种情况! - Arklur
67
尝试使用for i in data or []。这段代码的意思是,如果data是可迭代对象,则对其进行迭代操作;否则,迭代一个空列表。 - BMW
9
@nehemiah: 实际上,正确的方法不是检查data是否为None,而是让异常发生。您希望API的使用者知道他们何时使用不正确。接受None作为空序列会让像mylist = mylist.extend(morestuff)这样的错误更长时间地隐藏; 他们认为自己扩展了一个列表(他们确实这样做了,但立即用None替换它),然后将其传递给OP的函数,并想知道为什么文件是空的,没有任何错误被引发。 - ShadowRanger
1
@nehem Python的设计绝对没有缺陷。更严格的类型系统可以更轻松地发现错误。参见Rust、Haskell、Scala等语言。 - Mateen Ulhaq
显示剩余6条评论

118

错误解释:'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

NoneType很难发现,而且可能从lambda中“潜入”:

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的变量进行迭代。操作通过在None上调用__iter__方法来执行。

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

这就是为什么Python的鸭子类型思想被认为是不好的原因。程序员使用一个变量做了完全合理的事情,在运行时,它被None污染了,Python虚拟机试图继续运行,然后在地毯上吐了一堆无关的废话。

Java或C ++没有这些问题,因为这样的程序不会被编译,因为你还没有定义当出现None时该怎么做。Python允许程序员做很多在特殊情况下不能期望工作的事情,这给了程序员很大的自由度。Python是一个顺从的人,如果应该阻止您自我伤害,它说“是的,先生”,就像Java和C++那样。


2
(a) 混淆了 NoneTypeNone (b) 认为 NameError: name 'NoneType' is not definedTypeError: cannot concatenate 'str' and 'NoneType' objectsTypeError: 'NoneType' object is not iterable 是相同的 (c) Python 和 Java 的比较是 "一堆不相关的废话" - John Machin
4
如果你向期望接收任何集合类型的函数传递了null,Java基本上会面临相同的问题。C++在使用nullptr时也会遇到同样的问题(尽管通常只是在没有报告原因的情况下以分段错误崩溃)。尽管好的C++代码很少使用指针,但你展示的是不良Python代码,而糟糕的C++代码也可能在运行时由于空值而出错。Python在这里做得很正确;它并没有“继续前进”,而是在你尝试使用None无法完成的任何操作时立即报错。你的问题不在于Python,而在于动态类型语言。 - ShadowRanger

64

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

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

data 有什么问题吗?它的类型是 NoneType。只有 None 的类型是 NoneType。因此,data is None

您可以在 IDE 中验证这一点,或者在 for 语句之前插入例如 print "data is", repr(data) 并重新运行。

思考接下来需要做什么: 如何表示“没有数据”?我们写一个空文件吗?我们抛出异常或记录警告或保持沉默?


20

导致此错误的另一种情况是您将某物设置为从函数返回的内容,但忘记了实际返回任何内容。

例如:

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' object is not iterable in Python"实际上是在暗示"嘿,我正在尝试迭代返回值以按顺序将它们分配给这三个变量,但我只得到了None来迭代"


3
这正是我来这里的原因。那么对于这种情况,Pythonic 的解决方案是什么? - Dr_Zaszuś
1
似乎这里有一些帮助:https://dev59.com/PXM_5IYBdhLWcg3wrFMt - Dr_Zaszuś
1
Dr_Zaszus,这正是我的问题。这个特定的答案只是说确实存在问题。而且,被接受的答案基本上也只是说“是的,这会抛出一个错误”。整个线程缺乏实际、好的、被接受的做法来解决潜在的问题。提到的最好的解决方案是在评论中,即添加“if data is not None:”,这是一个丑陋的解决方案。 - user3685427

8
这意味着数据变量传递了None(它的类型是NoneType),相当于没有任何值。因此,它不能像列表一样进行迭代,就像您试图做的那样。

3
如果像一个空列表一样迭代,代码会更加简洁,减少错误检查。 - deltanine
4
@deltanine 我认为这会导致很多问题更难以检测。我很高兴None与空可迭代对象不同。如果你想使用你描述的行为,只需要使用for row in data or []: - Mark
@Mark,如果返回空列表的话,代码会更简洁。如果你想让它失败,你可以随时添加一行代码if data is None: raise - nehem

7

您正在调用write_file函数,参数如下:

write_file(foo, bar)

但是你没有正确定义 'foo',或者你的代码中有拼写错误,导致它创建一个新的空变量并将其传递了进去。


2
对我来说,这是一种情况,我的时髦的帽子代替了Python 3的帽子。
def函数的末尾忘记了return关键字。
几个月没有认真编写Python 3代码。一直以为例程中最后一个语句按照Groovy(或Rust)的方式被返回。
需要多次迭代,查看堆栈跟踪,在代码中插入try: ... except TypeError: ...块进行调试/逐步执行代码,才能找出问题所在。
对于该消息的解决方案肯定没有让错误立即显现出来。

1
这意味着dataNone,不可迭代。添加一个or []*可以防止异常并且不会输出任何内容:
for row in data or []:  # no more TypeError!
    print(row)

* 感谢之前的评论;请注意,引发异常可能也是期望的行为,或者是不当数据设置的指示器。


1

这还取决于您使用的Python版本。在我的情况下,Python 3.6和Python 3.8会抛出不同的错误消息,如下所示:

  • Python 3.6
(a,b) = None
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not iterable
  • Python 3.8
(a,b) = None
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: cannot unpack non-iterable NoneType object

0

因为使用for循环时,结果只是一个值而不是一组值。

pola.py

@app.route("/search")
def search():
    title='search'
    search_name =  request.form.get('search')
    
    search_item =   User.query.filter_by(id=search_name).first()

    return render_template('search.html', title=title, search_item=search_item  ) 

搜索.html(错误)
{% for p in search %}
{{ p }}

搜索.html(正确)
<td>{{ search_item  }}</td>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接