TypeError: Об’єкт "NoneType" не може бути ітерабельним у Python


145

Що означає помилка TypeError: 'NoneType' object is not iterable?

Я отримую це за цим 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)

Це одне з моїх роздратованих розчарувань у Python. Коли Noneїї примушують до послідовності, вона повинна створювати порожню послідовність, абсолютно нешкідливу.
nehem

7
@nehemiah: Python сильно набраний (просто не набраний статично). Noneніколи ні до чого не примушується . Маючи Noneтихо поводяться як і інші типи приховує помилки; це навпаки "нешкідливого". Якщо для порожньої послідовності вам потрібен помилковий заповнювач місця, ви можете використовувати ()або ''/ "", обидва з яких є одинаковими кнопками, і їх можна завантажити так само дешево None. Якщо ви хочете мовчки відмовитися від фальшивого поводження як порожньої послідовності, ви можете це зробити for row in data or ():, але ніхто цього не робить, тому що перехід Noneдо функції, яка очікує послідовність, - це помилка, яка не повинна пройти безшумно.
ShadowRanger

Відповіді:


203

Це означає, що значення dataє None.


37
Правильно, але загальний автор сценарію, призначений тут, полягає в тому, щоб пропустити forцикл, а не підняти виняток. Дизайн Python тут недосконалий. Коли Noneтрактується як ітерабельний, він повинен принаймні повертати порожній список. Цей виняток ніколи не допомагав нікому в реальному житті, крім того, щоб змусити нас вставити кілька потворних if data is not None:видів поводження.
nehem

Для більш конкретної відповіді, це може статися , якщо fieldlistдля DictWriterце None!
Арклюр

30
Спробуйтеfor i in data or []
BMW

4
@nehemiah: Насправді правильний підхід полягає не у тому, щоб перевірити, dataє чи ні None, а дозволити винятку. Ви хочете, щоб споживачі вашого API знали, коли вони неправильно його використовували. Прийняття Noneпорожньої послідовності дозволило б помилки, як mylist = mylist.extend(morestuff), вдається приховати ще довше; вони думають, що вони extendредагували list(і вони це зробили, але потім негайно замінили його None), а потім переходять до функції ОП і цікавляться, чому файл порожній, без будь-яких помилок.
ShadowRanger

83

Пояснення помилки: "NoneType" об'єкт не можна перетворити

У python2, NoneType - це тип None. У Python3 NoneType - клас None, наприклад:

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

Ітерація над змінною, яка має значення None Не відбувається:

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

Методи Python повертають NoneType, якщо вони не повертають значення:

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

Потрібно перевірити свої петельні конструкції на NoneType таким чином:

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

Гвідо каже, що використовувати його isпотрібно лише для перевірки, Noneоскільки isце більш надійно перевіряти особу. Не використовуйте операції з рівності, тому що вони можуть самостійно випльовувати міхурову реалізацію. Керівні принципи стилю кодування Python - PEP-008

Типи підступні і можуть прокрастися з лямбдів:

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

NoneType - недійсне ключове слово:

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

З'єднання Noneі рядок:

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

Що тут відбувається?

Інтерпретатор Python перетворив ваш код у байт-код pyc. Віртуальна машина Python обробляла байт-код, він наштовхувався на циклічну конструкцію, яка говорила про перехід змінної, що містить None. Операція була виконана шляхом виклику __iter__методу на None.

У жодному немає __iter__визначеного методу, тому віртуальна машина Python повідомляє вам, що він бачить: у NoneType немає __iter__методу.

Ось чому ідеологія типізації качок Python вважається поганою. Програміст робить щось цілком розумне зі змінною, і під час виконання його забруднюється Ніхто, віртуальна машина python намагається зайнятись солдатом, і набирає купу непов’язаних дурниць по всьому килиму.

У Java або C ++ немає цих проблем, оскільки таку програму не було б дозволено компілювати, оскільки ви не визначилися, що робити, коли не виникає None. Python дає програмісту багато мотузок, щоб він повісився, дозволяючи вам робити багато речей, над якими не можна очікувати роботи за виняткових обставин. Python - це людина, що говорить "так", коли це заважає вам заподіяти шкоду собі, як це робить Java та C ++.


2
(a) Confuses NoneTypeі None(b) вважає, що NameError: name 'NoneType' is not definedі TypeError: cannot concatenate 'str' and 'NoneType' objectsте саме, що TypeError: 'NoneType' object is not iterable(c) порівняння Python і java - "купа незв'язаних дурниць"
Джон Махін

3
Гм ... Java матиме по суті ідентичні проблеми, якби ви перейшли nullдо функції, яка очікує будь-якого типу колекції. C ++ матиме ту саму проблему (але, як правило, просто гине в сегментарі, не повідомляючи про причину) для nullptr(правда, хороший C ++ рідко використовує покажчики, але те, що ви продемонстрували, є поганим Python, і поганий C ++ може також померти під час виконання від нулів) . Тут Python робить правильну справу; це не "вояцтво", воно помиляється в той момент, коли ви намагаєтесь використати що- Noneнебудь, що Noneне може зробити. Ваша проблема не з Python, а з динамічно набраними мовами взагалі.
ShadowRanger

63

Код: for row in data:
Повідомлення про помилку:TypeError: 'NoneType' object is not iterable

На який об’єкт він скаржиться? Вибір двох rowі data. У for row in data, що має бути ітерабельним? Тільки data.

У чому проблема data? Його тип є NoneType. Тільки Noneмає тип NoneType. Отже data is None.

Ви можете перевірити це в IDE, або вставивши, наприклад, print "data is", repr(data)перед forоператором, та повторно запустивши.

Подумайте, що вам потрібно зробити далі: як слід "не представляти даних"? Ми пишемо порожній файл? Ми піднімаємо виняток чи записуємо попередження чи мовчимо?


18

Інша річ, яка може призвести до цієї помилки, це коли ви встановлюєте щось, що дорівнює поверненню від функції, але забули фактично повернути щось.

Приклад:

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)

Це трохи непомітна помилка, оскільки помилка також може бути створена, якщо змінна рядка на одному з ітерацій виявиться "None". Спосіб її виявити полягає в тому, що слід не проходить в останньому рядку, а не всередині функції.

Якщо ви перетворюєте лише одну змінну з функції, я не впевнений, що помилка буде видана ... Я підозрюю, що помилка "Об'єкт" NoneType "не є ітерабельним у Python", в цьому випадку насправді мається на увазі "Ей, я намагаюся перебирати значення повернення, щоб присвоїти їм ці три змінні в порядку, але я лише отримую Ні, щоб повторити "


1
Саме це і привело мене сюди. То що таке пітонічне рішення для такої ситуації?
Dr_Zaszuś

1
Схоже , що є якась - то допомога тут: stackoverflow.com/questions/1274875 / ...
Dr_Zaszuś

8

Це означає, що змінна даних не передає None (що є тип NoneType), її еквівалент ні за що . Тож це не може бути ітерабельним як список, як ви намагаєтесь зробити.


1
Було б добре, якби просто переглянуто, як порожній список ... хотів би отримати більш чистий код і менше перевірку помилок
дельтанін

4
@deltanine Можливо, для багатьох проблем буде важче виявити, я думаю. Я радий, що жоден не відрізняється від порожнього ітерабельного. Якщо ви хочете, щоб описана вами поведінка, просто використовуйтеfor row in data or []:
Марк

7

Ви викликаєте write_file з такими аргументами:

write_file(foo, bar)

Але ви неправильно не визначили "foo" або у вас є помилка друку у коді, щоб він створив нову порожню змінну та передав її.


1

Для мене це був випадок, коли замість Python 3 був мій капелюх Groovy .

Забули returnключове слово в кінці defфункції.

Не серйозно кодував Python 3 протягом декількох місяців. Думав, що остання заява, яку оцінювали в рутинному режимі, поверталася за способом Groovy.

Зробив кілька ітерацій, переглянувши слід стека, вставивши try: ... except TypeError: ...блок налагодження / перехід через код, щоб з'ясувати, що не так.

Рішення для повідомлення, безумовно, не змусило помилок вискочити на мене.


Дякую. Це була саме моя проблема. Я збирався зійти з розуму ...
Дж. Бретт Каннінгам
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.