TypeError: l'oggetto 'NoneType' non è iterabile in Python


145

Cosa significa errore TypeError: 'NoneType' object is not iterable?

Lo sto ottenendo su questo codice 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)

Questa è una delle mie fastidiose delusioni in Python. Quando Noneviene forzato in sequenza, deve produrre una sequenza vuota, totalmente innocua.
Nehem,

7
@nehemiah: Python è fortemente tipizzato (ma non tipizzato staticamente). Nonenon è mai costretto a nulla . Avere un Nonecomportamento silenzioso come altri tipi nasconde errori; questo è l' opposto di "innocuo". Se hai bisogno di un segnaposto falso per la sequenza vuota, puoi usare ()o ''/ "", entrambi i quali sono singoli e possono essere caricati in modo economico None. Se vuoi optare per il trattamento silenzioso di qualcosa di falso come una sequenza vuota, puoi farlo for row in data or ():, ma nessuno lo fa, perché passare Nonea una funzione in attesa di una sequenza è un errore che non dovrebbe passare silenziosamente.
ShadowRanger,

Risposte:


203

Significa che il valore di dataè None.


37
Corretto, ma l'autore dello scenario comune inteso qui è totalmente da saltare for ciclo invece di sollevare un'eccezione. Il design di Python è imperfetto qui. Quando Noneviene trattato come iterabile, deve restituire almeno un elenco vuoto. Questa eccezione non ha mai aiutato nessuno nella vita reale oltre a farci inserire qualche brutto if data is not None:tipo di gestione.
Nehem,

Per una risposta più concreta, può succedere se il fieldlistper DictWriterè None!
Arklur,

30
Provafor i in data or []
BMW

4
@nehemiah: In realtà, l'approccio corretto non è verificare se lo dataè o no None, ma lasciare che si verifichi l'eccezione. Vuoi che i consumatori della tua API sappiano quando l'hanno utilizzata in modo errato. Accettare Nonecome una sequenza vuota consentirebbe errori simili mylist = mylist.extend(morestuff), riuscendo a nascondersi ancora più a lungo; pensano di aver extendedlist (e l'hanno fatto, ma poi lo hanno immediatamente sostituito None), quindi lo passano alla funzione dell'OP e si chiedono perché il file sia vuoto, senza errori sollevati di alcun tipo.
ShadowRanger,

83

Spiegazione dell'errore: l'oggetto 'NoneType' non è iterabile

In python2, NoneType è il tipo di None. In Python3 NoneType è la classe di None, ad esempio:

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

L'iterazione su una variabile che ha valore None non riesce:

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

I metodi Python restituiscono NoneType se non restituiscono un valore:

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

Devi controllare i tuoi costrutti in loop per NoneType in questo modo:

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 dice che usare solo isper verificare Noneperché isè più robusto per il controllo dell'identità. Non usare le operazioni di uguaglianza perché quelle possono sputare l'implementazione del bubble-up. Linee guida sullo stile di codifica di Python - PEP-008

Nessuno I tipi sono subdoli e possono entrare di soppiatto da lambda:

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

NoneType non è una parola chiave valida:

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

Concatenazione di Nonee una stringa:

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

Cosa sta succedendo qui?

L'interprete di Python ha convertito il tuo codice in bytecode pyc. La macchina virtuale Python ha elaborato il bytecode, ha riscontrato un costrutto in loop che ha detto iterare su una variabile contenente None. L'operazione è stata eseguita invocando il__iter__ metodo su Nessuno.

Nessuno ha no __iter__ metodo definito, quindi la macchina virtuale di Python ti dice cosa vede: quel NoneType non ha alcun __iter__metodo.

Ecco perché l' ideologia della battuta d'anatra di Python è considerata negativa. Il programmatore fa qualcosa di completamente ragionevole con una variabile e in fase di esecuzione viene contaminato da None, la macchina virtuale Python tenta di fare il soldato e genera un mucchio di sciocchezze non correlate su tutto il tappeto.

Java o C ++ non hanno questi problemi perché non è possibile compilare un programma del genere poiché non è stato definito cosa fare quando si verifica Nessuno. Python dà al programmatore molta corda per impiccarsi permettendoti di fare molte cose che non ci si può aspettare che funzionino in circostanze eccezionali. Python è un sì-uomo, dice sì-signore quando ti impedisce di farti del male, come fa Java e C ++.


2
(a) Confonde NoneTypee None(b) pensa che NameError: name 'NoneType' is not definede TypeError: cannot concatenate 'str' and 'NoneType' objectssono gli stessi del TypeError: 'NoneType' object is not iterable(c) confronto tra Python e Java è "un mucchio di sciocchezze non correlate"
John Machin,

3
Umm ... Java avrebbe problemi sostanzialmente identici se si passasse nulla una funzione in attesa di qualsiasi tipo di raccolta. Il C ++ avrebbe lo stesso problema (ma generalmente muore in un segfault senza riportare la causa) perché nullptr(è vero, un buon C ++ usa raramente i puntatori, ma ciò che hai dimostrato è Python cattivo e anche un C ++ cattivo può morire in fase di esecuzione da zero) . Python sta facendo la cosa giusta qui; non è "fare soldi", si sta sbagliando nel momento in cui si tenta di utilizzare Noneper nulla che Nonenon si possa fare. Il tuo problema non è con Python, è con i linguaggi tipizzati dinamicamente in generale.
ShadowRanger,

63

Codice: for row in data:
messaggio di errore:TypeError: 'NoneType' object is not iterable

Di quale oggetto si lamenta? Scelta di due, rowe data. In for row in data, che deve essere iterabile? Solo data.

Qual è il problema data? Il suo tipo è NoneType. NoneHa solo tipo NoneType. Così data is None.

È possibile verificarlo in un IDE o inserendo ad esempio print "data is", repr(data)prima fordell'istruzione e rieseguendo.

Pensa a cosa devi fare dopo: come dovrebbe essere rappresentato "nessun dato"? Scriviamo un file vuoto? Facciamo un'eccezione o registriamo un avviso o restiamo in silenzio?


18

Un'altra cosa che può produrre questo errore è quando si imposta qualcosa uguale al ritorno da una funzione, ma si è dimenticato di restituire effettivamente qualcosa.

Esempio:

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)

Questo è un po 'un errore difficile da individuare perché l'errore può anche essere prodotto se la variabile di riga risulta essere Nessuna su una delle iterazioni. Il modo per individuarlo è che la traccia non riesce sull'ultima riga e non all'interno della funzione.

Se stai restituendo una sola variabile da una funzione, non sono sicuro che l'errore verrebbe prodotto ... Ho il sospetto che l'errore "L'oggetto" NoneType "non sia iterabile in Python" in questo caso implica in realtà "Ehi, sto provando per scorrere i valori restituiti per assegnarli a queste tre variabili in ordine, ma sto ricevendo solo Nessuno per scorrere "


1
Questo è esattamente ciò che mi ha portato qui. Allora, qual è la soluzione Pythonic per tale situazione?
Dr_Zaszuś,

1
Sembra che ci sia qualche aiuto qui: stackoverflow.com/questions/1274875/...
Dr_Zaszuś

8

Significa che la variabile di dati passa None (che è di tipo NoneType), il suo equivalente per niente . Quindi non può essere iterabile come elenco, come stai cercando di fare.


1
sarebbe bello se solo ripetesse come una lista vuota ... sarebbe nuda per un codice più pulito e meno controllo degli errori
deltanine

4
@deltanine Credo che molti problemi potrebbero essere più difficili da rilevare. Sono contento che nessuno sia diverso da un vuoto iterabile. Se vuoi il tuo comportamento descritto, usa semplicementefor row in data or []:
Marco

7

Stai chiamando write_file con argomenti come questo:

write_file(foo, bar)

Ma non hai definito correttamente "pippo" o hai un refuso nel tuo codice in modo che crei una nuova variabile vuota e la passi.


1

Per me è stato il caso di avere il mio cappello Groovy al posto di quello di Python 3.

Hai dimenticato la returnparola chiave alla fine di una deffunzione.

Non scrivevo sul serio Python 3 da un paio di mesi. Pensavo che l'ultima dichiarazione valutata nella routine fosse restituita secondo il modo Groovy.

Sono state eseguite alcune iterazioni, osservando la traccia dello stack, inserendo il try: ... except TypeError: ...debug dei blocchi / passando attraverso il codice per capire cosa non andava.

La soluzione per il messaggio certamente non mi ha fatto saltare per errore.


Grazie. Questo era esattamente il mio problema. Stavo per impazzire ...
J. Brett Cunningham il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.