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พฤติกรรมแบบเงียบ ๆ เหมือนกับประเภทอื่น ๆ จะซ่อนข้อผิดพลาด นั่นคือสิ่งที่ตรงกันข้ามกับ "ไม่เป็นอันตราย" หากคุณจำเป็นต้องมีตัวยึด falsy สำหรับลำดับที่ว่างเปล่าคุณสามารถใช้()หรือ''/ ""ซึ่งทั้งสองเป็น singletons Noneและสามารถโหลดได้เป็นอย่างถูก หากคุณต้องการเลือกที่จะรักษาสิ่งที่ไม่เหมาะสมเป็นลำดับว่างคุณสามารถทำได้for row in data or ():แต่ไม่มีใครทำอย่างนั้นเพราะผ่านNoneไปยังฟังก์ชันที่คาดว่าลำดับนั้นเป็นข้อผิดพลาดที่ไม่ควรผ่านอย่างเงียบ ๆ
ShadowRanger

คำตอบ:


203

มันหมายถึงค่าของการมีdataNone


37
ถูกต้อง แต่ผู้สร้างสถานการณ์ทั่วไปที่ตั้งใจไว้ที่นี่มีทั้งหมดเพื่อข้ามforลูปแทนการเพิ่มข้อยกเว้น การออกแบบของ Python มีข้อบกพร่องที่นี่ เมื่อNoneถือว่าเป็น iterable จะต้องส่งคืนรายการว่างเปล่าอย่างน้อย ข้อยกเว้นนี้ไม่ได้ช่วยใครในชีวิตจริงที่นอกเหนือจากการทำให้เราแทรกif data is not None:การจัดการที่น่าเกลียด
nehem

สำหรับคำตอบที่เป็นรูปธรรมมากขึ้นก็สามารถเกิดขึ้นได้หาก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

NoneType เป็นส่อเสียดและสามารถแอบเข้ามาจาก lambdas:

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

เกิดอะไรขึ้นที่นี่?

ล่ามของไพ ธ อนแปลงรหัสของคุณเป็น pyc bytecode เครื่องเสมือน Python ประมวลผล bytecode พบโครงสร้างลูปวนซึ่งกล่าวซ้ำมากกว่าตัวแปรที่มี None การดำเนินการถูกดำเนินการโดยเรียกใช้__iter__เมธอดบนไม่มี

ไม่มีไม่มี__iter__วิธีที่กำหนดไว้ดังนั้นเครื่องเสมือนของ Python จะบอกคุณถึงสิ่งที่เห็น: NoneType นั้นไม่มี__iter__วิธีการ

นี่คือเหตุผลที่อุดมการณ์การพิมพ์เป็ดของงูใหญ่ถือว่าไม่ดี โปรแกรมเมอร์ทำสิ่งที่สมเหตุสมผลอย่างสมบูรณ์กับตัวแปรและเมื่อรันไทม์จะได้รับการปนเปื้อนโดยไม่มีเครื่องเสมือนงูหลามพยายามที่จะทหารบนและ pukes เรื่องไร้สาระที่ไม่เกี่ยวข้องทั่วพรม

Java หรือ C ++ ไม่มีปัญหาเหล่านี้เนื่องจากโปรแกรมดังกล่าวจะไม่ได้รับอนุญาตให้รวบรวมเนื่องจากคุณไม่ได้กำหนดสิ่งที่ต้องทำเมื่อไม่มีเกิดขึ้น Python ให้เชือกโปรแกรมเมอร์จำนวนมากเพื่อแขวนตัวเองโดยอนุญาตให้คุณทำสิ่งต่าง ๆ มากมายที่ไม่ควรคาดว่าจะทำงานภายใต้สถานการณ์พิเศษ Python เป็นคนใช่โดยบอกว่าใช่เมื่อคุณต้องการหยุดคุณจากการทำร้ายตัวเองเช่นเดียวกับ Java และ C ++


2
(a) ความสับสน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 คือ "กลุ่มของเรื่องไร้สาระที่ไม่เกี่ยวข้อง"
John Machin

3
อืมม ... Java น่าจะมีปัญหาเหมือนกันถ้าคุณผ่านnullไปยังฟังก์ชันที่คาดว่าจะมีการรวบรวม C ++ จะมีปัญหาเดียวกัน (แต่โดยทั่วไปแล้วเพิ่งตายใน segfault โดยไม่รายงานสาเหตุ) สำหรับnullptr(เป็นที่ยอมรับว่า C ++ ที่ดีไม่ค่อยใช้พอยน์เตอร์ แต่สิ่งที่คุณแสดงให้เห็นคือ Python ไม่ดีและ C ++ ที่ไม่ดีสามารถตายจาก runtime ได้เช่นกัน) . Python กำลังทำสิ่งที่ถูกต้องที่นี่ ไม่ใช่ "ทหาร" เป็นข้อผิดพลาดเมื่อคุณพยายามใช้Noneในสิ่งที่Noneไม่สามารถทำได้ ปัญหาของคุณไม่ได้อยู่กับ Python แต่เป็นภาษาที่พิมพ์แบบไดนามิกโดยทั่วไป
ShadowRanger

63

รหัส: for row in data:
ข้อความผิดพลาด:TypeError: 'NoneType' object is not iterable

วัตถุใดที่บ่นเกี่ยวกับ? ทางเลือกของสองและrow dataในfor row in dataซึ่งจะต้อง iterable? 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)

นี่เป็นข้อผิดพลาดเล็กน้อยที่ยากที่จะสังเกตเห็นเนื่องจากข้อผิดพลาดสามารถเกิดขึ้นได้หากตัวแปรแถวเกิดขึ้นเป็นไม่มีในการทำซ้ำอย่างใดอย่างหนึ่ง วิธีที่จะสังเกตเห็นได้ว่าการสืบค้นกลับล้มเหลวในบรรทัดสุดท้ายและไม่ได้อยู่ในฟังก์ชัน

หากคุณส่งคืนตัวแปรเพียงตัวเดียวจากฟังก์ชั่นฉันไม่แน่ใจว่าข้อผิดพลาดนั้นจะเกิดขึ้นหรือไม่ ... ฉันสงสัยว่าข้อผิดพลาด "วัตถุ" ไม่มีประเภท "นั้นไม่สามารถใช้ซ้ำได้ใน Python" ในกรณีนี้ เพื่อวนซ้ำค่าที่ส่งคืนเพื่อกำหนดให้กับตัวแปรทั้งสามนี้ตามลำดับ แต่ฉันจะได้รับ None เพื่อวนซ้ำ "


1
นี่คือสิ่งที่ทำให้ฉันมาที่นี่ แล้ว Pythonic Solution สำหรับสถานการณ์เช่นนี้คืออะไร?
Dr_Zaszuś

1
ดูเหมือนว่ามีความช่วยเหลือบางอย่างที่นี่: stackoverflow.com/questions/1274875/…
Dr_Zaszuś

8

หมายความว่าตัวแปรข้อมูลผ่านไม่มี (ซึ่งเป็นประเภท NoneType) ซึ่งเทียบเท่ากับค่าใดๆ ดังนั้นจึงไม่สามารถทำซ้ำเป็นรายการได้ในขณะที่คุณพยายามทำ


1
มันคงจะดีถ้าเพียงซ้ำเช่นรายการที่ว่างเปล่า ... จะ Nake รหัสทำความสะอาดและน้อยกว่าการตรวจสอบข้อผิดพลาด
deltanine

4
@deltanine มันจะทำให้ปัญหามากมายเป็นเรื่องยากที่จะตรวจสอบฉันคิดว่า ฉันดีใจที่ไม่มีแตกต่างจากว่างเปล่า iterable หากคุณต้องการพฤติกรรมที่อธิบายของคุณเพียงใช้for row in data or []:
ทำเครื่องหมาย

7

คุณกำลังเรียกใช้ write_file โดยมีอาร์กิวเมนต์ดังนี้

write_file(foo, bar)

แต่คุณไม่ได้กำหนด 'foo' อย่างถูกต้องหรือคุณมีการพิมพ์ผิดในรหัสของคุณเพื่อให้มันสร้างตัวแปรว่างเปล่าใหม่และส่งผ่าน


1

สำหรับฉันมันเป็นกรณีของการมีของฉัน หมวก Groovyแทน Python 3

ลืมreturnคำค้นหาท้ายคำdefฟังก์ชั่น

ไม่ได้เขียนโปรแกรม Python 3 อย่างจริงจังเป็นเวลาสองเดือน การคิดประโยคสุดท้ายที่ประเมินในงานประจำถูกส่งคืนตามวิธี Groovy

ใช้การวนซ้ำสองสามครั้งดูที่การติดตามสแต็กแทรก try: ... except TypeError: ...บล็อกการดีบัก / การเหยียบรหัสผ่านเพื่อค้นหาว่ามีอะไรผิดปกติ

การแก้ปัญหาสำหรับข้อความอย่างแน่นอนไม่ได้ทำให้เกิดข้อผิดพลาดกระโดดออกมาที่ฉัน


ขอบคุณ. นี่เป็นปัญหาของฉันอย่างแน่นอน ฉันกำลังจะบ้าไปแล้ว ...
เจ. เบร็ทคันนิงแฮม
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.