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приводится в последовательность, оно должно создавать пустую последовательность, абсолютно безвредную.
Нехем

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

Ответы:


203

Это означает , что значение dataIS None.


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

Для более конкретного ответа, это может произойти, если fieldlistдля DictWriterэто None!
Arklur

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

4
@nehemiah: На самом деле, правильный подход не в том, чтобы проверить, dataесть или нет None, а в том, чтобы исключение произошло. Вы хотите, чтобы потребители вашего API знали, когда они использовали его неправильно. Принятие Noneв качестве пустой последовательности позволило бы ошибкам, подобным mylist = mylist.extend(morestuff), спрятаться еще дольше; они думают, что extendредактировали list(и сделали, но затем сразу же заменили его None), затем передают его в функцию OP и задаются вопросом, почему файл пуст, без каких-либо ошибок.
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

NoneTypes являются подлыми, и могут проникать из лямбд:

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 считается плохой. Программист делает что-то совершенно разумное с переменной, и во время выполнения она становится зараженной None, виртуальная машина python пытается воевать и набирает кучу несвязанной ерунды по всему ковру.

Java или C ++ не имеют этих проблем, потому что такая программа не может быть скомпилирована, так как вы не определили, что делать, когда ничего не происходит. Python дает программисту много веревки, чтобы повеситься, позволяя вам делать много вещей, которые не должны работать в исключительных обстоятельствах. Python - «да», он говорит «да-сэр», когда он мешает вам навредить себе, как это делают Java и C ++.


2
(а) Смущает NoneTypeи None(б) считает , что NameError: name 'NoneType' is not definedи TypeError: cannot concatenate 'str' and 'NoneType' objectsтакие же , как TypeError: 'NoneType' object is not iterable(в) сравнение между Python и Java является «кучу несвязанных нонсенс»
Джон Мачин

3
Умм ... У Java были бы по существу идентичные проблемы, если бы вы переходили nullк функции, ожидающей любого типа коллекции. C ++ будет иметь ту же проблему (но обычно просто умрет в segfault, не сообщая о причине) для 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" в этом случае фактически подразумевает "Эй, я пытаюсь перебрать возвращаемые значения, чтобы назначить их этим трем переменным по порядку, но я получаю только None для перебора "


1
Это именно то, что привело меня сюда. Так, каково Pythonic решение для такой ситуации?
Dr_Zaszuś

1
Похоже, что здесь есть некоторая помощь: stackoverflow.com/questions/1274875/…
Dr_Zaszuś

8

Это означает, что переменная данных передает None (тип NoneType), что эквивалентно ни за что . Так что он не может быть повторяем как список, как вы пытаетесь это сделать.


1
было бы неплохо, если бы просто итерация, как пустой список ... была бы полезна для более чистого кода и меньшей проверки ошибок
deltanine

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

7

Вы вызываете write_file с такими аргументами:

write_file(foo, bar)

Но вы не определили 'foo' правильно, или у вас есть опечатка в вашем коде, так что он создает новую пустую переменную и передает ее внутрь.


1

Для меня это был случай, когда у меня была заводная шляпа вместо Python 3 была .

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

Я не программировал Python 3 всерьез пару месяцев. Думал, что последнее утверждение, оцененное в рутине, возвращалось согласно Groovy

Сделал несколько итераций, просматривая трассировку стека, вставляя try: ... except TypeError: ... блок отладки / пошаговое выполнение кода, чтобы выяснить, в чем дело.

Решение для сообщения конечно не заставило ошибку выскакивать у меня.


Спасибо. Это была именно моя проблема. Я собирался сходить с ума ...
Дж. Бретт Каннингем
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.