TypeError: o objeto 'NoneType' não é iterável no Python

145

O que TypeError: 'NoneType' object is not iterablesignifica error ?

Estou recebendo este código 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)
eu--''''''---------''''''''''''
fonte
Esta é uma das minhas decepções irritantes em Python. Quando Noneé coagido como uma sequência, deve produzir uma sequência vazia, totalmente inofensiva.
1/17
7
@ nehemiah: Python é fortemente tipado (apenas não estaticamente). Nonenunca é coagido a nada . Ter um Nonecomportamento silencioso como outros tipos oculta erros; isso é o oposto de "inofensivo". Se você precisar de um espaço reservado falso para a sequência vazia, poderá usar ()ou ''/ "", os quais são singletons e podem ser carregados o mais barato possível None. Se você deseja optar por tratar silenciosamente qualquer coisa falsa como uma sequência vazia, pode fazê-lo for row in data or ():, mas ninguém faz isso, porque passar Nonepara uma função que espera uma sequência é um erro que não deve passar silenciosamente.
ShadowRanger 5/10

Respostas:

203

Isso significa que o valor de dataé None.

vanza
fonte
37
Correto, mas o autor comum do cenário pretendido aqui é totalmente ignorar o forloop em vez de gerar uma exceção. O design do Python é falho aqui. Quando Noneé tratado como iterável, ele deve retornar pelo menos a lista vazia. Essa exceção nunca ajudou ninguém na vida real a não ser nos fazer inserir alguns if data is not None:tipos feios de manuseio.
1/17
Para uma resposta mais concreta, pode acontecer se o fieldlistfor DictWriterfor None!
Arklur
30
Tentefor i in data or []
BMW
4
@nehemiah: Na verdade, a abordagem correta não é verificar se dataexiste ou não None, mas permitir que a exceção ocorra. Você deseja que os consumidores da sua API saibam quando a usaram incorretamente. Aceitar Nonecomo uma sequência vazia deixaria erros como mylist = mylist.extend(morestuff), conseguir se esconder ainda mais; eles acham que extendeditaram um list(e o fizeram, mas o substituíram imediatamente por None), depois o passam para a função do OP e se perguntam por que o arquivo está vazio, sem erros de qualquer tipo.
ShadowRanger 5/10
83

Explicação do erro: O objeto 'NoneType' não é iterável

Em python2, NoneType é o tipo de None. No Python3, NoneType é a classe None, por exemplo:

>>> 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.

A iteração sobre uma variável com valor Nenhum falha:

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

Os métodos Python retornam NoneType se eles não retornam um valor:

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

Você precisa verificar suas construções de loop para NoneType assim:

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 diz que apenas use ispara verificar Noneporque isé mais robusto para verificação de identidade. Não use operações de igualdade porque elas podem cuspir implementações próprias. Diretrizes de estilo de codificação do Python - PEP-008

Os tipos são furtivos e podem se infiltrar a partir de lambdas:

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

NoneType não é uma palavra-chave válida:

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

Concatenação de Nonee uma string:

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

O que está acontecendo aqui?

O intérprete do Python converteu seu código em bycode pyc. A máquina virtual Python processou o bytecode, encontrou uma construção em loop que dizia iterar sobre uma variável que continha None. A operação foi realizada invocando o __iter__método no None.

Nenhum possui um __iter__método definido, portanto, a máquina virtual do Python diz o que vê: que o NoneType não tem __iter__método.

É por isso que a ideologia de digitação de pato do Python é considerada ruim. O programador faz algo completamente razoável com uma variável e, em tempo de execução, é contaminado por None, a máquina virtual python tenta resistir e solta um monte de besteiras não relacionadas por todo o tapete.

Java ou C ++ não tem esses problemas porque esse programa não poderia ser compilado, pois você não definiu o que fazer quando nenhum ocorrer. O Python dá ao programador muita corda para se enforcar, permitindo que você faça muitas coisas que não se espera que funcionem em circunstâncias excepcionais. O Python é um sim-homem, dizendo sim-senhor quando o impede de se prejudicar, como Java e C ++ fazem.

Eric Leschinski
fonte
2
(a) confunde NoneTypee None(b) pensa que NameError: name 'NoneType' is not definede TypeError: cannot concatenate 'str' and 'NoneType' objectssão os mesmos que TypeError: 'NoneType' object is not iterable(c) comparação entre Python e Java é "um monte de bobagens não relacionada"
John Machin
3
Umm ... Java teria problemas essencialmente idênticos se você passasse nullpara uma função que espera qualquer tipo de coleção. C ++ teria o mesmo problema (mas geralmente apenas morre em um segfault sem relatar a causa) para nullptr(reconhecidamente, um bom C ++ raramente usa ponteiros, mas o que você demonstrou é um Python ruim e um C ++ ruim também pode morrer em tempo de execução de nulos) . Python está fazendo a coisa correta aqui; não é "soldado", está errando no momento em que você tenta usar Nonepara algo Noneque não pode fazer. Seu problema não é com o Python, é com linguagens tipadas dinamicamente em geral.
ShadowRanger
63

Código: for row in data:
Mensagem de erro:TypeError: 'NoneType' object is not iterable

De que objeto está reclamando? Escolha de dois, rowe data. Em for row in data, o que precisa ser iterável? Só data.

Qual é o problema data? Seu tipo é NoneType. Só Nonetem tipo NoneType. Então data is None.

Você pode verificar isso em um IDE ou inserindo, por exemplo, print "data is", repr(data)antes da forinstrução e executando novamente.

Pense no que você precisa fazer a seguir: como "nenhum dado" deve ser representado? Nós escrevemos um arquivo vazio? Criamos uma exceção ou registramos um aviso ou ficamos em silêncio?

John Machin
fonte
18

Outra coisa que pode produzir esse erro é quando você está configurando algo igual ao retorno de uma função, mas esqueceu de realmente retornar qualquer coisa.

Exemplo:

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)

Esse é um erro difícil de detectar, porque o erro também pode ser produzido se a variável de linha for None em uma das iterações. A maneira de detectar isso é que o rastreamento falha na última linha e não dentro da função.

Se você estiver retornando apenas uma variável de uma função, não tenho certeza se o erro seria produzido ... Suspeito que o erro "O objeto 'NoneType' não seja iterável no Python". Nesse caso, na verdade está implicando "Ei, estou tentando para iterar sobre os valores de retorno para atribuí-los a essas três variáveis ​​em ordem, mas só estou obtendo Nenhum para iterar "

pistoleiro
fonte
1
Foi exatamente isso que me trouxe aqui. Então, qual é a solução pitônica para essa situação?
Dr_Zaszuś 5/1018
1
Parece que há alguma ajuda aqui: stackoverflow.com/questions/1274875/…
Dr_Zaszuś
8

Isso significa que a variável de dados está passando None (que é do tipo NoneType), seu equivalente para nada . Portanto, não pode ser iterável como uma lista, como você está tentando fazer.

Cajado
fonte
1
seria bom se apenas iterado como uma lista vazia ... seria Nake para um código mais limpo e menos verificação de erros
deltanine
4
@ deltanine Isso tornaria muitos problemas mais difíceis de detectar, eu acho. Fico feliz que nenhum seja diferente de um iterável vazio. Se você quiser o seu comportamento descrito, basta usar #for row in data or []:
Mark
7

Você está chamando write_file com argumentos como este:

write_file(foo, bar)

Mas você não definiu 'foo' corretamente ou possui um erro de digitação no código, para que ele crie uma nova variável vazia e a transmita.

clee
fonte
1

Para mim, foi o caso de usar meu chapéu Groovy em vez do chapéu do Python 3.

Esqueceu a returnpalavra-chave no final de uma deffunção.

Não estava codificando Python 3 a sério há alguns meses. Estava pensando que a última declaração avaliada na rotina estava sendo retornada pela maneira Groovy.

Realizou algumas iterações, observando o rastreamento da pilha, inserindo a try: ... except TypeError: ...depuração de bloco / percorrendo o código para descobrir o que estava errado.

A solução para a mensagem certamente não cometeu o erro.

JGFMK
fonte
Obrigado. Este foi exatamente o meu problema. Eu estava prestes a enlouquecer ...
J. Brett Cunningham