Python ตรวจสอบว่า isinstance ประเภทใดในรายการหรือไม่?


90

ฉันจะทำอย่างไร:

var = 7.0
var_is_good = isinstance(var, classinfo1) or isinstance(var, classinfo2) or isinstance(var, classinfo3) or ... or  isinstance(var, classinfoN)

ดูเหมือนงี่เง่าที่ฉันไม่สามารถส่งผ่านรายการ classinfo ของ:

var_is_good = isinstanceofany( var, [classinfo1, classinfo2, ... , classinfoN] )

แล้วisinstanceofanyฟังก์ชั่นคืออะไร?


ถ้ามันบวกเลขลบเหมือนจำนวนคูณเหมือนจำนวน ... ทำไมถึงต้องรู้ว่ามันเป็นตัวเลข? ดูการพิมพ์เป็ดสำหรับรายละเอียดเพิ่มเติม
Makoto

กรณีการใช้งานเฉพาะของฉันมีฟังก์ชันที่ส่งคืน a (ฟังก์ชันที่ส่งคืน (เช่น a numberหรือส่งคืนนิพจน์ sympy)) ฉันต้องการตรวจสอบว่าฟังก์ชันที่ฉันสร้างขึ้นนั้นทำในสิ่งที่ควรทำเมื่อฉันส่งต่อไปยังฟังก์ชันอื่น ๆ
D Adams

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

ฉันเดาว่าฉันสามารถส่งคืนนิพจน์ที่เห็นอกเห็นใจซึ่งบางครั้งประเมินเป็นตัวเลขและบางครั้งก็มีตัวแปรหลงเหลืออยู่ภายใน
D Adams

นั่นคือสิ่งที่ฉันคิดว่าคุณต้องการทำที่นี่ แทนที่จะส่งคืนประเภทที่แตกต่างกันหลายประเภทให้ส่งคืนประเภทเดียวและหากจำเป็นให้ลดเป็นตัวเลขแทน
Makoto

คำตอบ:


200

isinstance()ยิงtupleของชั้นเรียนสำหรับอาร์กิวเมนต์ที่สอง มันจะคืนค่าเป็นจริงหากอาร์กิวเมนต์แรกเป็นตัวอย่างของประเภทใด ๆในลำดับนั้น:

isinstance(var, (classinfo1, classinfo2, classinfo3))

กล่าวอีกนัยหนึ่งคือมีฟังก์ชันนี้isinstance() อยู่แล้วนอกกรอบ

จากisinstance()เอกสารประกอบ :

ถ้าclassinfoไม่ใช่ทั้ง class object หรือ type object ก็อาจเป็น tuple ของ class หรือ type object หรืออาจมี tuples อื่น ๆ แบบวนซ้ำก็ได้ (ไม่ยอมรับประเภทลำดับอื่น ๆ )

เน้นเหมือง; สังเกตลักษณะการเกิดซ้ำ;(classinfo1, (classinfo2, classinfo3))ยังเป็นตัวเลือกที่ถูกต้อง


12

คุณค่อนข้างสนิทกับชื่อคำถามของคุณแล้ว คุณสามารถใช้anyและรายการ:

var = 7.0
var_is_good = any([isinstance(var, classinfo1),
                   isinstance(var, classinfo2),
                   isinstance(var, classinfo3), ...
                   isinstance(var, classinfoN)])

แต่ดูในเอกสารisinstanceเปิดเผย:

ส่งกลับจริงถ้าอาร์กิวเมนต์อ็อบเจ็กต์เป็นอินสแตนซ์ของอาร์กิวเมนต์ classinfo หรือคลาสย่อย (ทางตรงทางอ้อมหรือเสมือน) ของคลาสย่อยดังกล่าว ถ้าอ็อบเจกต์ไม่ใช่อ็อบเจ็กต์ประเภทที่กำหนดฟังก์ชันจะคืนค่าเป็นเท็จเสมอ ถ้า classinfo ไม่ใช่คลาส (ออบเจ็กต์ประเภท) อาจเป็นทูเปิลของอ็อบเจ็กต์ประเภทหรืออาจมีทูเพิลอื่น ๆ ซ้ำ (ไม่ยอมรับประเภทลำดับอื่น ๆ ) ถ้า classinfo ไม่ใช่ type หรือ tuple ของ types และ tuples ดังกล่าวข้อยกเว้น TypeError จะเพิ่ม

ซึ่งหมายความว่าวิธีที่ดีกว่าคือ

var = 7.0
var_is_good = isinstance(var, (classinfo1,
                               classinfo2,
                               classinfo3,
                               ...,
                               classinfoN))

2
การทำซ้ำisinstanceเฉพาะการclassinfoเปลี่ยนแปลงดูเหมือนจะไม่เป็น Pythonic สำหรับฉัน
Makoto

1
ลอง var.__class__. นั่นคือสิ่งที่คุณต้องการ? @ Makoto: ฉันเห็นด้วย ไม่ใช่ Pythonic เลย!
ฟลาเมงโก

@ มาโกโตะยุ. แต่นั่นเป็นสิ่งที่ D Adams อาจพบได้ง่ายโดยการค้นหาเอกสารสำหรับ "any" ฉันได้ขยายคำตอบไปยังเวอร์ชันที่ดีกว่า ... แต่เห็นได้ชัดว่า Martijn Pieters เร็วกว่า ... อีกครั้ง
Martin Thoma

3
any()กับรายการคือ .. ไม่มีจุดหมาย ใช้นิพจน์ตัวสร้างหากคุณต้องใช้any()อย่างน้อยคุณก็จะได้รับประโยชน์จากการออกก่อนกำหนด
Martijn Pieters

ฉันคิดว่าการisinstanceมีทูเพิลเป็นวิธีที่จะไป ฉันแค่อยากจะพูดถึงวิธีแก้ปัญหาด้วยanyเพราะดูเหมือนว่าเขาจะขอในชื่อเรื่อง
Martin Thoma

4

วิธีนี้จะช่วยแก้ปัญหาของคุณ:

valid_instance_types = <tuple of types you want to allow>
var_is_good = isinstance(var, valid_instance_types)

บนพื้นฐานของเอกสารisinstanceมีหลายวิธีที่คุณสามารถส่งผ่านค่าของชนิดใน

คุณอาจดูยั่วยวนหากคุณพยายามตรวจสอบความถูกต้องที่ซับซ้อนมากขึ้นซึ่งนี่เป็นเพียงส่วนหนึ่ง


isinstance () มีฟังก์ชันนี้อยู่แล้วส่ง tuple พร้อมกับประเภทที่จำเป็นทั้งหมดเพื่อตรวจสอบเป็นอาร์กิวเมนต์ที่ 2
RFV

@ RFV5s ใช่ .... นั่นคือตัวอย่างที่ฉันให้ไว้ที่นี่ คุณคัดค้านอะไร
Nathaniel Ford

1

โดยทั่วไปคุณไม่ควรใช้isinstanceแต่สิ่งที่คุณต้องการทำสามารถทำได้ด้วยฟังก์ชัน builtin ใด ๆ ()

var_is_good = any(isinstance(var, t) for t in [type1, type2, type3])

7
นี่คือ overkill; มีฟังก์ชันการทำงานออกจากกล่องโดยไม่ต้องใช้isinstance() any()
Martijn Pieters

@MartijnPieters ฉันไม่ทราบว่า isinstance สามารถมีได้หลายประเภท แต่ฉันรู้สึกว่าคำตอบนั้นยังคงดีอยู่เพราะคำถามสามารถตอบได้กว้างขึ้นว่าเป็น "ฉันจะตรวจสอบได้อย่างไรว่าค่าที่ส่งคืนจากฟังก์ชันเฉพาะ ด้วยพารามิเตอร์ที่แตกต่างกันเป็นจริง "
Chad S.

คุณควรใช้หรือไม่isinstance()นั้นไม่เกี่ยวข้อง
RFV

@ ชาดส. ฉันอยากจะถามคุณว่าทำไมคุณถึงคิดว่าเขาไม่ควรใช้isinstance()? ขอขอบคุณ.
idature

เนื่องจากหลามหลีกเลี่ยงการตรวจสอบประเภท เป็นรหัสพิเศษจำนวนมาก (และรอบ CPU) เพื่อประโยชน์เพียงเล็กน้อย พิมพ์เป็ดเป็นที่ต้องการ
Chad S.
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.