TypeError: l'objet 'NoneType' n'est pas itérable en Python


145

Que signifie l'erreur TypeError: 'NoneType' object is not iterable?

Je l'obtiens sur ce code 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)

C'est l'une de mes ennuyeuses déceptions en Python. Lorsqu'il Noneest contraint en une séquence, il doit produire une séquence vide, totalement inoffensive.
nehem

7
@nehemiah: Python est fortement typé (mais pas statiquement typé). Nonen'est jamais contraint à quoi que ce soit . Le fait de Nonese comporter en silence comme les autres types cache les erreurs; c'est le contraire de «inoffensif». Si vous avez besoin d'un espace réservé faux pour la séquence vide, vous pouvez utiliser ()ou ''/ "", qui sont tous deux des singletons et peuvent être chargés à un prix aussi avantageux que None. Si vous voulez choisir de traiter silencieusement tout ce qui est faux comme une séquence vide, vous pouvez le faire for row in data or ():, mais personne ne le fait, car passer Noneà une fonction qui attend une séquence est une erreur qui ne devrait pas passer en silence.
ShadowRanger

Réponses:


203

Cela signifie que la valeur de dataest None.


37
Correct, mais l'auteur de scénario commun destiné ici est totalement de sauter la forboucle au lieu de lever une exception. La conception de Python est imparfaite ici. Quand Noneest traité comme un itérable, il doit au moins renvoyer une liste vide. Cette exception n'a jamais aidé personne dans la vraie vie à part nous obliger à insérer quelques if data is not None:types de manipulation horribles .
nehem

Pour une réponse plus concrète, cela peut arriver si le fieldlistpour le DictWriterest None!
Arklur

30
Essayerfor i in data or []
BMW

4
@nehemiah: En fait, la bonne approche n'est pas de vérifier si datac'est le cas ou non None, mais de laisser l'exception se produire. Vous voulez que les consommateurs de votre API sachent lorsqu'ils ne l'ont pas utilisée correctement. Accepter Nonecomme une séquence vide laisserait des erreurs comme mylist = mylist.extend(morestuff), réussir à se cacher encore plus longtemps; ils pensent qu'ils ont extendédité un list(et ils l'ont fait, mais l'ont immédiatement remplacé par None), puis le passent à la fonction de l'OP et se demandent pourquoi le fichier est vide, sans erreur d'aucune sorte.
ShadowRanger

83

Explication de l'erreur: l'objet 'NoneType' n'est pas itérable

En python2, NoneType est le type de None. En Python3, NoneType est la classe de None, par exemple:

>>> 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'itération sur une variable qui a la valeur None échoue:

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

Les méthodes Python retournent NoneType si elles ne renvoient pas de valeur:

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

Vous devez vérifier vos constructions en boucle pour NoneType comme ceci:

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 dit seulement utiliser ispour vérifier Nonecar il isest plus robuste à la vérification d'identité. N'utilisez pas les opérations d'égalité, car elles peuvent cracher leur propre implémentation. Directives de style de codage de Python - PEP-008

Aucun Les types sont sournois et peuvent se faufiler à 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'est pas un mot clé valide:

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

Concaténation de Noneet d'une chaîne:

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

Que se passe t-il ici?

L'interpréteur de Python a converti votre code en bytecode pyc. La machine virtuelle Python a traité le bytecode, elle a rencontré une construction en boucle qui disait itérer sur une variable contenant None. L'opération a été effectuée en invoquant la __iter__méthode sur None.

Aucun n'a aucune __iter__méthode définie, donc la machine virtuelle de Python vous dit ce qu'elle voit: que NoneType n'a pas de __iter__méthode.

C'est pourquoi l' idéologie de type canard de Python est considérée comme mauvaise. Le programmeur fait quelque chose de tout à fait raisonnable avec une variable et au moment de l'exécution, il est contaminé par None, la machine virtuelle python tente de persévérer et vomit un tas de bêtises sans rapport sur le tapis.

Java ou C ++ n'ont pas ces problèmes car un tel programme ne serait pas autorisé à se compiler puisque vous n'avez pas défini quoi faire lorsque None se produit. Python donne au programmeur beaucoup de cordes pour se pendre en vous permettant de faire beaucoup de choses qui ne devraient pas fonctionner dans des circonstances exceptionnelles. Python est un oui-homme, disant oui-monsieur quand il veut vous empêcher de vous faire du mal, comme le font Java et C ++.


2
(a) confond NoneTypeet None(b) pense que NameError: name 'NoneType' is not definedet TypeError: cannot concatenate 'str' and 'NoneType' objectssont les mêmes que TypeError: 'NoneType' object is not iterable(c) la comparaison entre Python et java est "un tas de non-sens sans rapport"
John Machin

3
Umm ... Java aurait des problèmes essentiellement identiques si vous passiez nullà une fonction qui attend n'importe quel type de collection. C ++ aurait le même problème (mais généralement mourir dans un segfault sans signaler la cause) pour nullptr(certes, un bon C ++ utilise rarement des pointeurs, mais ce que vous avez démontré est un mauvais Python, et un mauvais C ++ peut aussi mourir à l'exécution à partir de valeurs nulles) . Python fait la bonne chose ici; ce n'est pas "soldat sur", c'est une erreur au moment où vous essayez d'utiliser Nonepour quelque chose Nonene peut pas faire. Votre problème n'est pas avec Python, c'est avec les langages typés dynamiquement en général.
ShadowRanger

63

Code: for row in data:
Message d'erreur:TypeError: 'NoneType' object is not iterable

De quel objet se plaint-il? Choix de deux, rowet data. Dans for row in data, qui doit être itérable? Seulement data.

Quel est le problème data? Son type est NoneType. A seulement le Nonetype NoneType. Alors data is None.

Vous pouvez le vérifier dans un IDE, ou en insérant par exemple print "data is", repr(data)avant l' forinstruction et en le relançant.

Réfléchissez à ce que vous devez faire ensuite: comment représenter «aucune donnée»? Écrivons-nous un fichier vide? Levons-nous une exception, enregistrons-nous un avertissement ou gardons-nous le silence?


18

Une autre chose qui peut produire cette erreur est lorsque vous définissez quelque chose égal au retour d'une fonction, mais que vous avez oublié de retourner quoi que ce soit.

Exemple:

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)

C'est un peu une erreur difficile à repérer car l'erreur peut également être produite si la variable de ligne se trouve être None sur l'une des itérations. Le moyen de le repérer est que la trace échoue sur la dernière ligne et non à l'intérieur de la fonction.

Si vous ne renvoyez qu'une seule variable d'une fonction, je ne suis pas sûr si l'erreur serait produite ... Je soupçonne que l'erreur "L'objet 'NoneType' n'est pas itérable en Python" dans ce cas implique en fait "Hey, j'essaye pour itérer sur les valeurs de retour pour les affecter à ces trois variables dans l'ordre, mais je n'obtiens aucun pour itérer "


1
C'est exactement ce qui m'a amené ici. Alors, quelle est la solution pythonique pour une telle situation?
Dr_Zaszuś

1
Il semble qu'il y ait de l'aide ici: stackoverflow.com/questions/1274875/…
Dr_Zaszuś

8

Cela signifie que la variable de données passe None (qui est de type NoneType), son équivalent pour rien . Il ne peut donc pas être itérable sous forme de liste, comme vous essayez de le faire.


1
ce serait bien si juste itéré comme une liste vide ... serait nake pour un code plus propre et moins de vérification des erreurs
deltanine

4
@deltanine Cela rendrait beaucoup de problèmes plus difficiles à détecter je pense. Je suis content qu'aucun ne soit différent d'un itérable vide. Si vous voulez votre comportement décrit, utilisez simplementfor row in data or []:
Mark

7

Vous appelez write_file avec des arguments comme celui-ci:

write_file(foo, bar)

Mais vous n'avez pas défini correctement 'foo', ou vous avez une faute de frappe dans votre code afin qu'il crée une nouvelle variable vide et la passe.


1

Pour moi, il s'agissait d'avoir mon chapeau Groovy au lieu de celui de Python 3.

J'ai oublié le returnmot - clé à la fin d'une deffonction.

Je n'avais pas vraiment codé Python 3 depuis quelques mois. Je pensais que la dernière déclaration évaluée dans la routine était renvoyée selon la méthode Groovy.

J'ai pris quelques itérations, en regardant la trace de la pile, en insérant try: ... except TypeError: ...le débogage de bloc / en parcourant le code pour comprendre ce qui n'allait pas.

La solution du message ne m'a certainement pas fait sauter l'erreur.


Je vous remercie. C'était exactement mon problème. J'étais sur le point de devenir fou ...
J. Brett Cunningham
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.