TypeError: 'NoneType' nesnesi Python'da yinelenemez


145

Hata ne anlama TypeError: 'NoneType' object is not iterablegeliyor?

Bu Python kodunu alıyorum:

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)

Bu Python'daki can sıkıcı hayal kırıklığımdan biri. Tüm Nonedizi olarak coerced tamamen zararsız boş dizisi üretmek gerekir.
nehem

7
@nehemiah: Python güçlü bir şekilde yazılmıştır (sadece statik olarak yazılmamıştır). Nonehiçbir şeye zorlanmaz . Having Nonediğer tiplerin derileri hatalar gibi davranmaya sessizce; bu "zararsız" ın tersidir . Boş dizi için yanlış bir yer tutucusuna ihtiyacınız varsa , her ikisi de tekli olan ve / ()veya ucuz olarak yüklenebilen veya ''/ kullanabilirsiniz . Yanlış olan herhangi bir şeyi boş bir sekans olarak sessizce tedavi etmeyi seçmek istiyorsanız, bunu yapabilirsiniz , ancak hiç kimse bunu yapmaz, çünkü bir sekans bekleyen bir işleve geçmek sessizce geçmemesi gereken bir hatadır. ""Nonefor row in data or ():None
ShadowRanger

Yanıtlar:


203

Bu değerini, dataIS None.


37
Doğru, Ama burada amaçlanan ortak senaryo yazarı forbir istisna oluşturmak yerine tamamen döngüyü atlamaktır. Python'un tasarımı burada kusurlu. Ne zaman Nonebir iterable olarak kabul edilir ki, en azından boş liste dönmelidir. Bu istisna, gerçek hayatta hiç kimseye birkaç çirkin if data is not None:işlem yapmamıza yardımcı olmadı .
nehem

Daha somut bir cevap için, eğer başına gelebilecek fieldlistiçin DictWriterolduğunu None!
Arklur

30
Deneyinfor i in data or []
BMW

4
@nehemiah: Aslında, doğru yaklaşım olup olmadığını kontrol etmek datadeğil None, istisnanın gerçekleşmesine izin vermektir. API'nızın tüketicilerinin onu ne zaman yanlış kullandıklarını bilmelerini istiyorsunuz . NoneBoş bir dizi olarak kabul etmek , hataların mylist = mylist.extend(morestuff)daha uzun süre gizlenmesini sağlar; bir extended edildiklerini düşünüyorlar list(ve yaptılar, ancak hemen değiştirdiler None), daha sonra OP işlevine aktardılar ve dosyanın neden boş olduğunu merak ettiler, herhangi bir hata oluşmadı.
ShadowRanger

83

Hatanın açıklaması: 'NoneType' nesnesi yinelenemez

Python2'de NoneType, None türündedir. Python3'te NoneType, None sınıfıdır, örneğin:

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

Yok değerine sahip bir değişken üzerinde yineleme başarısız olur:

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

Python yöntemleri bir değer döndürmezlerse NoneType döndürür:

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

Döngü yapılarınızı NoneType için aşağıdaki gibi kontrol etmeniz gerekir:

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, sadece iskontrol etmek için kullandığını söylüyor Noneçünkü iskimlik kontrolüne daha dayanıklı. Eşitlik operasyonlarını kullanmayın, çünkü bunlar kendi başlarına kabarmış uygulamalara tükürebilir. Python'un Kodlama Stili Yönergeleri - PEP-008

Türler Sinsi ve lambdaslardan gizlice girebilir:

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

NoneType geçerli bir anahtar kelime değil:

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

NoneBir dizenin birleşimi ve bir dize:

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

Burada neler oluyor?

Python'un tercümanı kodunuzu pyc bayt koduna dönüştürdü. Python sanal makinesi bayt kodunu işledi, None içeren bir değişken üzerinde yinelemeyi söyleyen bir döngü yapısıyla karşılaştı. İşlem, Yok'taki __iter__yöntem çağrılarak gerçekleştirildi .

Hiçbirinin __iter__tanımlı bir yöntemi yoktur , bu nedenle Python'un sanal makinesi gördüklerini söyler: NoneType'ın hiçbir __iter__yöntemi yoktur .

Bu yüzden Python'un ördek yazma ideolojisi kötü olarak kabul edilir. Programcı bir değişkenle tamamen makul bir şey yapar ve çalışma zamanında Yok tarafından kontamine olur, python sanal makinesi askere gitmeye çalışır ve halının her yerinde bir sürü ilgisiz saçmalık ortaya çıkarır.

Java veya C ++ bu sorunlara sahip değildir, çünkü Hiçbiri oluştuğunda ne yapacağınızı tanımlamadığınız için böyle bir programın derlenmesine izin verilmez. Python, istisnai durumlarda çalışması beklenemeyecek çok şey yapmanıza izin vererek programcıya kendini asması için birçok ip verir. Python, Java ve C ++ gibi, kendinize zarar vermemenizi engellediğinde evet efendim diyor.


2
(a) karıştırır NoneTypeve None(b) düşündüğü NameError: name 'NoneType' is not definedve TypeError: cannot concatenate 'str' and 'NoneType' objectsaynıdır TypeError: 'NoneType' object is not iterable(c) Python ve Java ile karşılaştırılması "ilişkisiz saçma bir grup" olduğu
John Machin

3
Hımm ... nullHerhangi bir koleksiyon türü bekleyen bir işleve geçerseniz Java'nın temelde aynı sorunları olur . C ++ aynı soruna sahip olurdu (ancak genellikle nedeni bildirmeden bir segfaultta ölür) nullptr(kuşkusuz, iyi C ++ nadiren işaretçiler kullanır, ancak gösterdiğiniz şey kötü Python'dur ve kötü C ++ çalışma zamanında boş değerlerden de ölebilir) . Python burada doğru olanı yapıyor; "Askerlik" değil, yapamayacağınız Nonehiçbir şey için kullanmaya çalıştığınız an hata veriyor None. Sorununuz Python ile değil, genel olarak dinamik olarak yazılmış dillerle ilgili.
ShadowRanger

63

Kod: for row in data:
Hata mesajı:TypeError: 'NoneType' object is not iterable

Hangi nesne hakkında şikayet ediyor? İki seçim rowve data. In for row in dataihtiyacı iterable olunur? Sadece data.

Sorun ne data? Türü NoneType. Yalnızca Nonetürü vardır NoneType. Yani data is None.

Bunu bir IDE'de veya örneğin ifadeden print "data is", repr(data)önce ekleyerek forve yeniden çalıştırarak doğrulayabilirsiniz.

Daha sonra ne yapmanız gerektiğini düşünün: "Hiçbir veri" nasıl temsil edilmemelidir? Boş bir dosya yazar mıyız? Bir istisna oluşturur veya bir uyarı kaydeder miyiz yoksa sessiz mi kalırız?


18

Bu hatayı üretebilecek başka bir şey, bir işlevden geri dönüşe eşit bir şey ayarladığınız, ancak aslında bir şey döndürmeyi unuttuğunuzdur.

Misal:

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)

Bu, nokta değişkeninin yinelemelerden birinde Yok olması durumunda hata da üretilebildiğinden, tespit edilmesi biraz zor bir hatadır. Bunu tespit etmenin yolu, izin işlevin içinde değil, son satırda başarısız olmasıdır.

Eğer bir fonksiyondan sadece bir değişken döndürürseniz, hatanın üretilip üretilmeyeceğinden emin değilim ... Bu durumda aslında "Hey, deniyorum bu üç değişkene sırayla onları atamak için dönüş değerlerini yinelemek için, ancak yalnızca hiçbirini yinelemem "


1
Beni buraya getiren de buydu. Peki böyle bir durum için Pythonic çözümü nedir?
Dr_Zaszuś

1
Burada biraz yardım var gibi görünüyor: stackoverflow.com/questions/1274875/…
Dr_Zaszuś

8

Veri değişken için eşdeğeri (tip NoneType olan) Hiçbiri geçen demektir şey . Yani yapmaya çalıştığınız gibi bir liste olarak tekrarlanamaz.


1
boş bir liste gibi yinelenen güzel olurdu ... daha temiz kod ve daha az hata kontrolü için nake olurdu
deltanine

4
@deltanine Bence bir çok problemi tespit etmek daha zor olur. Hiçbirinin boş bir yinelemeden farklı olmadığına sevindim. Açıklanan davranışınızı istiyorsanız, sadecefor row in data or []:
Mark

7

Buna benzer argümanlarla write_file diyorsunuz:

write_file(foo, bar)

Ancak 'foo'yu doğru bir şekilde tanımlayamadınız ya da kodunuzda yeni bir boş değişken oluşturup onu geçirecek bir yazım hatası var.


1

Benim için Python 3 yerine Groovy şapkamı takmıştım .

returnBir deffonksiyonun sonunda anahtar kelimeyi unuttum .

Birkaç aydır ciddi Python 3 kodlamamıştı. Rutin değerlendirilen son ifadenin Groovy yöntemine göre döndürüldüğünü düşünüyordum.

try: ... except TypeError: ...Neyin yanlış olduğunu anlamak için blok hata ayıklama / kodlama adımını ekleyerek yığın izlemesine bakarak birkaç yineleme yapıldı.

Mesajın çözümü kesinlikle hatayı bana atlatmadı.


Teşekkür ederim. Bu benim sorunumdu.
J. Brett Cunningham
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.