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

Posted

技术标签:

【中文标题】TypeError:“NoneType”对象在 Python 中不可迭代【英文标题】:TypeError: 'NoneType' object is not iterable in Python 【发布时间】:2011-04-22 16:34:11 【问题描述】:

错误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 被强制转换为序列时,它必须产生一个空序列,完全无害。 @nehemiah:Python 是强类型的(只是不是静态类型的)。 None 永远不会被强制anything。让None 像其他类型一样默默地隐藏错误;那是“无害”的相反。如果你需要一个虚假的占位符来表示空序列,你可以使用()''/"",它们都是单例,并且可以像None 一样便宜地加载。如果您想选择以静默方式将任何虚假的内容视为空序列,您可以执行for row in data or ():,但没有人这样做,因为将None 传递给期望序列的函数是一个不应静默传递的错误. 在 python 2 中安装不再支持 python 2 的模块时,您也可能会收到此错误,例如***.com/q/63346648/838494 @nehem 你一定是 javascript 的粉丝。 @MattYoon JS 做对了很多事情。 【参考方案1】:

表示data的值为None

【讨论】:

正确,但是作者在这里打算完全跳过for 循环而不是引发异常。 Python 的设计在这里有缺陷。当None 被视为可迭代时,它必须至少返回空列表。除了让我们插入一些丑陋的if data is not None: 处理之外,这个例外对现实生活中的任何人都没有帮助。 对于更具体的答案,如果DictWriterfieldlistNone,则可能会发生这种情况! 试试for i in data or [] @nehemiah:其实正确的做法不是检查data是不是None,而是让异常发生。您希望 API 的使用者知道他们何时错误地使用了它。接受None 为空序列会让mylist = mylist.extend(morestuff) 之类的错误隐藏得更久;他们认为他们 extended a list(他们确实做到了,但随后立即将其替换为 None),然后将其传递给 OP 的函数,并想知道为什么文件是空的,没有引发任何错误。 【参考方案2】:

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

write_file(foo, bar)

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

【讨论】:

【参考方案3】:

这意味着数据变量传递的是None(类型为NoneType),它相当于nothing。所以它不能像你试图做的那样作为一个列表进行迭代。

【讨论】:

如果像一个空列表一样迭代就好了……这样代码更简洁,错误检查更少 @deltanine 我认为这会使很多问题更难检测。我很高兴 None 与空的可迭代对象不同。如果你想要你描述的行为,只需使用for row in data or []: @Mark 如果它返回空列表,它会更干净。如果您希望它失败,您可以随时添加一行 if data is None: raise【参考方案4】:

代码: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 语句之前,然后重新运行。

想想你接下来需要做什么: “无数据”应该如何表示?我们写一个空文件吗?我们是引发异常、记录警告还是保持沉默?

【讨论】:

【参考方案5】:

错误解释:“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's Coding Style Guidelines - PEP-008

NoneTypes 是偷偷摸摸的,可以从 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 的变量。该操作是通过在 None 上调用 __iter__ 方法来执行的。

None 没有定义 __iter__ 方法,所以 Python 的虚拟机告诉你它看到了什么:NoneType 没有 __iter__ 方法。

这就是为什么Python's duck-typing 意识形态被认为是坏的。程序员对变量做了一些完全合理的事情,在运行时它被 None 污染,python 虚拟机试图继续前进,并在地毯上吐出一堆不相关的废话。

Java 或 C++ 没有这些问题,因为这样的程序不会被允许编译,因为你还没有定义当 None 发生时要做什么。 Python 允许你做很多在特殊情况下不应该做的事情,从而给程序员提供了很多可以吊死自己的绳索。 Python 是一个“是”的人,当它阻止你伤害自己时说“是”,先生,就像 Java 和 C++ 一样。

【讨论】:

(a) 混淆NoneTypeNone (b) 认为NameError: name 'NoneType' is not definedTypeError: cannot concatenate 'str' and 'NoneType' objectsTypeError: cannot concatenate 'str' and 'NoneType' objects 一样 (c) Python 和java 比较是“一堆无关的废话” 嗯...如果您将null 传递给期望任何集合类型的函数,Java 将遇到基本相同的问题。对于nullptr,C++ 也会有同样的问题(但通常只是在段错误中死掉而不报告原因)(诚然,好的 C++ 很少使用指针,但你所展示的是糟糕的 Python,而糟糕的 C++ 可能会在运行时从也为空)。 Python在这里做的是正确的事情;这不是“继续战斗”,当您尝试使用None 做任何None 做不到的事情时,它就会出错。您的问题不在于 Python,而在于一般的动态类型语言。【参考方案6】:

另一个可能产生此错误的情况是,当您设置的值等于函数的返回值,但忘记实际返回任何值。

例子:

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 来迭代"

【讨论】:

这正是把我带到这里的原因。那么针对这种情况的 Pythonic 解决方案是什么? 这里好像有帮助:***.com/questions/1274875/… Dr_Zaszus 这也是我的问题。这个特定的答案只是说确实存在问题。而且,接受的答案基本上也只是说“是的,这会引发错误”。整个线程没有解决潜在问题的实际、良好、公认的实践答案。提到的最佳解决方案是在注释中,即添加“if data is not None:”,这是一个丑陋的解决方案。【参考方案7】:

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

忘记了def 函数末尾的return 关键字。

已经有几个月没有认真编写 Python 3 代码了。认为在例程中评估的最后一条语句是按照 Groovy(或 Rust)方式返回的。

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

消息的解决方案当然没有让我跳出错误。

【讨论】:

【参考方案8】:

当你得到无异常时继续循环,

示例:

   a = None
   if a is None:
       continue
   else:
       print("do something")

这可以是来自 DB 或 excel 文件的任何可迭代对象。

【讨论】:

【参考方案9】:

这还取决于您使用的 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

【讨论】:

以上是关于TypeError:“NoneType”对象在 Python 中不可迭代的主要内容,如果未能解决你的问题,请参考以下文章

在执行并行 ssh 时获取“TypeError:'NoneType' 对象不可迭代”

TypeError:“NoneType”对象在函数中不可下标

Anvil 错误:TypeError:“NoneType”对象不可下标

TypeError:调用键函数时“NoneType”对象不可迭代

TypeError:“NoneType”类型的对象在尝试适合 KerasCLassifier 时没有 len()

运行测试时突然出现“TypeError:'NoneType'对象不可迭代