TypeError: Obiekt „NoneType” nie jest iterowalny w Pythonie


145

Co oznacza błąd TypeError: 'NoneType' object is not iterable?

Dostaję to na tym kodzie Pythona:

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)

To jedno z moich irytujących rozczarowań w Pythonie. Kiedy Nonejest wymuszony jako sekwencja, musi wytworzyć pustą sekwencję, całkowicie nieszkodliwą.
nehem

7
@nehemiah: Python jest silnie wpisywany (tylko nie jest typowany statycznie). Nonenigdy nie jest do niczego zmuszany . Mając Nonecicho zachowywać się jak błędy innych rodzajów skór; to przeciwieństwo „nieszkodliwego”. Jeśli potrzebujesz fałszywego symbolu zastępczego dla pustej sekwencji, możesz użyć ()lub ''/ "", z których oba są singletonami i można je załadować równie tanio jak None. Jeśli chcesz wyrazić zgodę na ciche traktowanie czegoś fałszywego jako pustej sekwencji, możesz to zrobić for row in data or ():, ale nikt tego nie robi, ponieważ przekazanie Nonedo funkcji oczekującej sekwencji jest błędem, który nie powinien przejść cicho.
ShadowRanger

Odpowiedzi:


203

Oznacza to, że wartość datajest None.


37
Prawidłowo, ale typowy autor scenariusza zamierzał tutaj całkowicie pominąć forpętlę zamiast zgłaszać wyjątek. Projekt Pythona jest tutaj wadliwy. Gdy Nonejest traktowany jako iterowalny, musi zwracać przynajmniej pustą listę. Ten wyjątek nigdy nie pomógł nikomu w prawdziwym życiu, poza zmuszeniem nas do wprowadzenia kilku brzydkich if data is not None:sposobów obsługi.
nehem

Aby uzyskać bardziej konkretną odpowiedź, może się to zdarzyć, jeśli fieldlisttak DictWriterjest None!
Arklur

30
Spróbujfor i in data or []
BMW

4
@nehemiah: Właściwie właściwym podejściem nie jest sprawdzanie, czy tak datajest, czy nie None, ale pozwolenie na wystąpienie wyjątku. Ty chcesz konsumentów swojego API wiedzieć kiedy używałem go nieprawidłowo. Akceptacja Nonejako pusta sekwencja pozwoliłaby takim błędom mylist = mylist.extend(morestuff)ukryć się jeszcze dłużej; myślą, że wydali extenda list(i zrobili, ale natychmiast zastąpili go None), a następnie przekazują go do funkcji OP i zastanawiają się, dlaczego plik jest pusty, bez żadnych błędów.
ShadowRanger

83

Wyjaśnienie błędu: Obiekt „NoneType” nie jest iterowalny

W python2 NoneType jest typem None. W Python3 NoneType jest klasą None, na przykład:

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

Iteracja po zmiennej, która ma wartość None kończy się niepowodzeniem:

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

Metody Pythona zwracają NoneType, jeśli nie zwracają wartości:

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

Musisz sprawdzić konstrukcje zapętlające dla NoneType w następujący sposób:

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 mówi, że używaj tylko isdo sprawdzania, Noneponieważ isjest bardziej odporny na sprawdzanie tożsamości. Nie używaj operacji równościowych, ponieważ mogą one same wypluć wybuchowe zapalenie. Wytyczne dotyczące stylu kodowania w Pythonie - PEP-008

NoneTypes są Sneaky i mogą wkraść się z lambd:

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

NoneType nie jest prawidłowym słowem kluczowym:

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

Łączenie Nonei ciąg znaków:

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

Co tu się dzieje?

Interpreter Pythona przekonwertował twój kod na kod bajtowy pyc. Maszyna wirtualna Pythona przetworzyła kod bajtowy, napotkała konstrukcję zapętloną, która mówi, że wykonuje iterację po zmiennej zawierającej None. Operacja została wykonana przez wywołanie __iter__metody na None.

Żadna nie ma __iter__zdefiniowanej metody, więc maszyna wirtualna Pythona mówi ci, co widzi: że NoneType nie ma __iter__metody.

Właśnie dlatego ideologia pisania na klawiaturze w Pythonie jest uważana za złą. Programista robi coś całkiem rozsądnego ze zmienną i w czasie wykonywania zostaje ona skażona przez Brak, maszyna wirtualna Pythona próbuje się do niej przyłączyć i wymiotuje po całym dywanie garść niepowiązanych bzdur.

Java lub C ++ nie ma tych problemów, ponieważ taki program nie mógłby się kompilować, ponieważ nie zdefiniowano, co zrobić, gdy wystąpi Brak. Python daje programiście mnóstwo liny do powieszenia, pozwalając ci robić wiele rzeczy, od których nie można oczekiwać, że zadziałają w wyjątkowych okolicznościach. Python jest człowiekiem na tak, mówiąc tak, proszę pana, gdy ma to na celu powstrzymanie cię przed wyrządzeniem sobie krzywdy, tak jak robią to Java i C ++.


2
(a) Zamieszanie NoneTypei None(b) myśli, że NameError: name 'NoneType' is not definedi TypeError: cannot concatenate 'str' and 'NoneType' objectssą tym samym, co TypeError: 'NoneType' object is not iterable(c) porównanie Pythona i javy to „garść niepowiązanych bzdur”
John Machin

3
Umm ... Java miałaby zasadniczo identyczne problemy, gdybyś przekazał ją nulldo funkcji oczekującej dowolnego typu kolekcji. C ++ miałby ten sam problem (ale generalnie po prostu ginie w segfault bez zgłaszania przyczyny) dla nullptr(wprawdzie dobry C ++ rzadko używa wskaźników, ale to, co pokazałeś, to zły Python, a zły C ++ może również umrzeć w czasie wykonywania z null) . Python robi tutaj właściwą rzecz; to nie jest „żołnierz”, to błąd w momencie, gdy próbujesz użyć Noneczegoś, Noneczego nie możesz zrobić. Twój problem nie dotyczy Pythona, ale ogólnie języków dynamicznie typowanych.
ShadowRanger

63

Kod: for row in data:
Komunikat o błędzie:TypeError: 'NoneType' object is not iterable

Na jaki przedmiot narzeka? Do wyboru dwa rowi data. W for row in data, która musi być iterowalna? Tylko data.

W czym problem data ? Jego typ to NoneType. NoneMa tylko typ NoneType. A więc data is None.

Możesz to sprawdzić w IDE lub wstawiając np. print "data is", repr(data)Przed forinstrukcją i uruchamiając ponownie.

Zastanów się, co musisz zrobić dalej: jak należy przedstawić „brak danych”? Czy piszemy pusty plik? Czy zgłaszamy wyjątek, rejestrujemy ostrzeżenie lub milczymy?


18

Inną rzeczą, która może spowodować ten błąd, jest ustawienie wartości równej zwrotowi z funkcji, ale zapomnieliśmy o zwróceniu czegokolwiek.

Przykład:

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)

Jest to trochę trudny do wykrycia błąd, ponieważ błąd można również wygenerować, jeśli zmienna wierszowa ma wartość None w jednej z iteracji. Sposobem na to jest to, że śledzenie kończy się niepowodzeniem w ostatnim wierszu, a nie w funkcji.

Jeśli zwracasz tylko jedną zmienną z funkcji, nie jestem pewien, czy błąd zostałby wygenerowany ... Podejrzewam, że błąd „Obiekt 'NoneType' nie jest iterowalny w Pythonie” w tym przypadku oznacza to „Hej, próbuję aby iterować po zwracanych wartościach, aby przypisać je do tych trzech zmiennych w kolejności, ale otrzymuję tylko None do iteracji ”


1
Właśnie to mnie tu sprowadziło. Więc jakie jest rozwiązanie Pythonic na taką sytuację?
Dr_Zaszuś

1
Wygląda na to, że jest tu jakaś pomoc: stackoverflow.com/questions/1274875/…
Dr_Zaszuś

8

Oznacza to, że zmienna data przekazuje wartość None (która jest typu NoneType), jej odpowiednik dla niczego . Więc nie może być iterowalne jako lista, tak jak próbujesz to zrobić.


1
byłoby miło, gdyby tylko powtórzyć jak pusta lista ... byłoby nake kodu czystsze i mniej sprawdzanie błędów
DeltaNine

4
@deltanine Myślę, że wiele problemów byłoby trudniejszych do wykrycia. Cieszę się, że Żaden nie różni się od pustej iteracji. Jeśli chcesz opisać swoje zachowanie, po prostu użyjfor row in data or []:
Mark

7

Wołasz write_file z następującymi argumentami:

write_file(foo, bar)

Ale nie zdefiniowałeś poprawnie 'foo' lub masz literówkę w kodzie, tak że tworzy nową pustą zmienną i przekazuje ją.


1

Dla mnie był to przypadek posiadania mojej czapki Groovy zamiast Pythona 3.

Zapomniałem returnsłowa kluczowego na końcu deffunkcji.

Przez kilka miesięcy nie pisał na poważnie Pythona 3. Czy myślałem, że ostatnie stwierdzenie ocenione w rutynach zostało zwrócone w sposób Groovy.

Wykonałem kilka iteracji, patrząc na ślad stosu, wstawiając try: ... except TypeError: ...debugowanie blokowe / przechodzenie przez kod, aby dowiedzieć się, co jest nie tak.

Rozwiązanie komunikatu na pewno nie sprawiło, że błąd wyskoczył na mnie.


Dziękuję Ci. To był dokładnie mój problem. Miałem zwariować ...
J. Brett Cunningham
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.