TypeError: Das Objekt 'NoneType' kann in Python nicht iteriert werden


145

Was bedeutet Fehler TypeError: 'NoneType' object is not iterable?

Ich bekomme es auf diesen Python-Code:

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)

Dies ist eine meiner nervigen Enttäuschungen in Python. Wenn Nonees als Sequenz erzwungen wird, muss es eine leere Sequenz erzeugen, die völlig harmlos ist.
Nehem

7
@nehemiah: Python ist stark typisiert (nur nicht statisch typisiert). Nonewird nie zu irgendetwas gezwungen . Wenn Sie sich Nonestill wie andere Typen verhalten, werden Fehler ausgeblendet. das ist das Gegenteil von "harmlos". Wenn Sie einen falschen Platzhalter für die leere Sequenz benötigen, können Sie ()oder ''/ verwenden "", die beide Singletons sind und so billig wie geladen werden können None. Wenn Sie sich dafür entscheiden möchten, etwas Falsches stillschweigend als leere Sequenz zu behandeln, können Sie dies tun for row in data or ():, aber niemand tut dies, da das Übergeben Nonean eine Funktion, die eine Sequenz erwartet, ein Fehler ist, der nicht stillschweigend übergeben werden sollte.
ShadowRanger

Antworten:


203

Es bedeutet, dass der Wert von dataist None.


37
Richtig, aber der hier beabsichtigte allgemeine Szenarioautor ist es, die forSchleife vollständig zu überspringen , anstatt eine Ausnahme auszulösen. Pythons Design ist hier fehlerhaft. Wenn Nonees als iterabel behandelt wird, muss es mindestens eine leere Liste zurückgeben. Diese Ausnahme hat niemandem im wirklichen Leben geholfen, außer uns dazu zu bringen, einige hässliche if data is not None:Arten der Handhabung einzufügen .
Nehem

Für eine konkretere Antwort kann es passieren, wenn das fieldlistfür das DictWriterist None!
Arklur

30
Versuchen Siefor i in data or []
BMW

4
@nehemiah: Eigentlich besteht der richtige Ansatz nicht darin, zu überprüfen, ob dies der Fall dataist oder nicht None, sondern die Ausnahme auftreten zu lassen. Sie möchten, dass die Benutzer Ihrer API wissen, wenn sie sie falsch verwendet haben. Das Akzeptieren Noneals leere Sequenz würde es Fehlern ermöglichen mylist = mylist.extend(morestuff), sich noch länger zu verstecken. Sie denken, sie haben ein extendEd erstellt list(und sie haben es getan, es aber sofort durch ersetzt None), es dann an die OP-Funktion übergeben und sich gefragt, warum die Datei leer ist, ohne dass irgendwelche Fehler aufgetreten sind.
ShadowRanger

83

Erläuterung des Fehlers: Das Objekt 'NoneType' kann nicht iteriert werden

In Python2 ist NoneType der Typ None. In Python3 ist NoneType die Klasse None, zum Beispiel:

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

Das Iterieren über eine Variable mit dem Wert None schlägt fehl:

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

Python-Methoden geben NoneType zurück, wenn sie keinen Wert zurückgeben:

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

Sie müssen Ihre Schleifenkonstrukte wie folgt auf NoneType überprüfen:

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 sagt, nur verwenden is, um zu prüfen, Noneweil isist robuster für die Identitätsprüfung. Verwenden Sie keine Gleichstellungsoperationen, da diese selbst eine Bubble-up-Implementierungsentzündung auslösen können. Pythons Richtlinien für den Codierungsstil - PEP-008

NoneTypes sind hinterhältig und können sich von Lambdas einschleichen:

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

NoneType ist kein gültiges Schlüsselwort:

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

Verkettung von Noneund eine Zeichenfolge:

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

Was ist denn hier los?

Der Python-Interpreter hat Ihren Code in Pyc-Bytecode konvertiert. Die virtuelle Python-Maschine verarbeitete den Bytecode und stieß auf ein Schleifenkonstrukt, das über eine Variable iterierte, die None enthielt. Die Operation wurde ausgeführt, indem die __iter__Methode für None aufgerufen wurde.

Für None ist keine __iter__Methode definiert, daher sagt Ihnen die virtuelle Maschine von Python, was sie sieht: NoneType hat keine __iter__Methode.

Aus diesem Grund wird Pythons Ideologie der Ententypisierung als schlecht angesehen. Der Programmierer macht mit einer Variablen etwas völlig Vernünftiges und zur Laufzeit wird sie durch None kontaminiert. Die virtuelle Python-Maschine versucht, Soldaten zu werden, und kotzt eine Menge Unsinn auf dem ganzen Teppich.

Java oder C ++ haben diese Probleme nicht, da ein solches Programm nicht kompiliert werden darf, da Sie nicht definiert haben, was zu tun ist, wenn None auftritt. Python gibt dem Programmierer viel Seil, um sich aufzuhängen, indem es Ihnen ermöglicht, viele Dinge zu tun, von denen nicht erwartet werden kann, dass sie unter außergewöhnlichen Umständen funktionieren. Python ist ein Ja-Mann, der Ja-Sir sagt, wenn es darum geht, Sie davon abzuhalten, sich selbst Schaden zuzufügen, wie es Java und C ++ tun.


2
(a) verwirrt NoneTypeund None(b) denkt, dass NameError: name 'NoneType' is not definedund TypeError: cannot concatenate 'str' and 'NoneType' objectsist das gleiche wie TypeError: 'NoneType' object is not iterable(c) Vergleich zwischen Python und Java ist "ein Haufen nicht verwandten Unsinns"
John Machin

3
Umm ... Java hätte im Wesentlichen identische Probleme, wenn Sie an nulleine Funktion übergeben würden, die einen Auflistungstyp erwartet. C ++ hätte das gleiche Problem (stirbt aber im Allgemeinen nur in einem Segfault, ohne die Ursache zu melden) für nullptr(zugegebenermaßen verwendet gutes C ++ selten Zeiger, aber was Sie gezeigt haben, ist schlechtes Python, und schlechtes C ++ kann zur Laufzeit auch an Nullen sterben) . Python macht hier das Richtige; Es ist kein "Soldat", sondern ein Fehler in dem Moment, in dem Sie versuchen, Noneetwas zu verwenden, was Nonenicht möglich ist. Ihr Problem liegt nicht bei Python, sondern bei dynamisch typisierten Sprachen im Allgemeinen.
ShadowRanger

63

Code: for row in data:
Fehlermeldung:TypeError: 'NoneType' object is not iterable

Über welches Objekt beschwert es sich? Wahl von zwei rowund data. In for row in data, was muss iterierbar sein? Nur data.

Was ist das Problem mit data? Sein Typ ist NoneType. Hat Nonenur Typ NoneType. Also data is None.

Sie können dies in einer IDE überprüfen oder z. B. print "data is", repr(data)vor der forAnweisung einfügen und erneut ausführen.

Überlegen Sie, was Sie als Nächstes tun müssen: Wie sollen "keine Daten" dargestellt werden? Schreiben wir eine leere Datei? Lösen wir eine Ausnahme aus oder protokollieren wir eine Warnung oder schweigen wir?


18

Eine andere Sache, die diesen Fehler verursachen kann, ist, wenn Sie etwas festlegen, das der Rückgabe einer Funktion entspricht, aber vergessen haben, tatsächlich etwas zurückzugeben.

Beispiel:

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)

Dies ist ein schwieriger Fehler, da der Fehler auch auftreten kann, wenn die Zeilenvariable in einer der Iterationen zufällig None ist. Der Weg, dies zu erkennen, besteht darin, dass die Ablaufverfolgung in der letzten Zeile und nicht innerhalb der Funktion fehlschlägt.

Wenn Sie nur eine Variable von einer Funktion zurückgeben, bin ich mir nicht sicher, ob der Fehler auftreten würde ... Ich vermute, dass der Fehler "Das Objekt 'NoneType' ist in Python nicht iterierbar" in diesem Fall tatsächlich impliziert: "Hey, ich versuche es über die Rückgabewerte zu iterieren, um sie diesen drei Variablen der Reihe nach zuzuweisen, aber ich bekomme nur None, um zu iterieren "


1
Genau das hat mich hierher gebracht. Was ist die pythonische Lösung für eine solche Situation?
Dr_Zaszuś

1
Es scheint, als gäbe es hier Hilfe: stackoverflow.com/questions/1274875/…
Dr_Zaszuś

8

Dies bedeutet, dass die Datenvariable None (der Typ NoneType) übergibt, was für nichts gleichwertig ist . Es kann also nicht als Liste iteriert werden, wie Sie es versuchen.


1
Es wäre schön, wenn nur wie eine leere Liste iteriert würde ... würde für saubereren Code und weniger Fehlerprüfung
nake

4
@deltanine Es würde dazu führen, dass viele Probleme schwieriger zu erkennen sind, denke ich. Ich bin froh, dass sich keiner von einem leeren iterable unterscheidet. Wenn Sie Ihr beschriebenes Verhalten wollen, verwenden Sie einfachfor row in data or []:
Mark

7

Sie rufen write_file mit folgenden Argumenten auf:

write_file(foo, bar)

Aber Sie haben 'foo' nicht richtig definiert oder Sie haben einen Tippfehler in Ihrem Code, so dass eine neue leere Variable erstellt und übergeben wird.


1

Für mich war es ein Fall von meinem darum Groovy-Hut anstelle des Python 3- Hutes aufzusetzen .

Ich habe das vergessen return Schlüsselwort am Ende einer defFunktion .

Hatte Python 3 seit ein paar Monaten nicht mehr ernsthaft programmiert. Dachte, die letzte in der Routine ausgewertete Aussage wurde nach dem Groovy-Verfahren zurückgegeben.

Es dauerte einige Iterationen, sah sich die Stapelverfolgung an und fügte sie ein try: ... except TypeError: ... Block-Debugging / Durchlaufen des Codes ein, um herauszufinden, was falsch war.

Die Lösung für die Nachricht hat den Fehler sicherlich nicht dazu gebracht, mich anzuspringen.


Danke dir. Das war genau mein Problem. Ich wollte verrückt werden ...
J. Brett Cunningham
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.