Python: การเพิ่มข้อยกเว้นภายใน __init__ เป็นรูปแบบที่ไม่ดีหรือไม่?


128

การเพิ่มข้อยกเว้นภายในถือเป็นรูปแบบที่ไม่ดี__init__หรือไม่? ถ้าเป็นเช่นนั้นวิธีการใดที่ยอมรับได้ในการส่งข้อผิดพลาดเมื่อตัวแปรคลาสบางตัวเริ่มต้นเป็นNoneหรือประเภทที่ไม่ถูกต้อง


ใน C เป็นรูปแบบที่ไม่ดีในการเพิ่มข้อยกเว้นในตัวทำลาย แต่ตัวสร้างควรจะใช้ได้
Calyth

6
@Calyth คุณหมายถึง C ++ - ไม่มีตัวสร้างหรือตัวทำลายใน C.
Alex Martelli

4
... หรือข้อยกเว้นสำหรับเรื่องนั้น
Matt Wilding

@Calyth: ฮ่า ๆ โปรดลบคำพูดไร้สาระที่เกิดจากการพิมพ์ผิดที่ไร้เดียงสา ;-)
lpapp

4
@lpapp ใช่ C ++ บัดซบ และฉันไม่สามารถแก้ไขความคิดเห็นนั้นได้ ดังนั้นอินเทอร์เน็ตจะบันทึกความงี่เง่าของฉัน;)
Calyth

คำตอบ:


160

การเพิ่มข้อยกเว้นภายใน__init__()ทำได้ดีอย่างแน่นอน ไม่มีวิธีอื่นที่ดีในการระบุเงื่อนไขข้อผิดพลาดภายในตัวสร้างและมีหลายร้อยตัวอย่างในไลบรารีมาตรฐานที่การสร้างวัตถุสามารถทำให้เกิดข้อยกเว้นได้

แน่นอนว่าระดับข้อผิดพลาดที่จะเพิ่มขึ้นอยู่กับคุณ ValueErrorจะดีที่สุดหากตัวสร้างส่งผ่านพารามิเตอร์ที่ไม่ถูกต้อง


14
ยกเว้นที่ใช้มากที่สุดในตัวสร้างเป็นและValueError TypeError
Denis Otkidach

9
เพียงแค่ชี้ให้เห็นว่านั่น__init__ไม่ใช่ตัวสร้าง แต่เป็น Intializer คุณอาจต้องการแก้ไขบรรทัดไม่มีวิธีอื่นที่ดีในการระบุเงื่อนไขข้อผิดพลาดภายในตัวสร้าง, ..
Haris

27

เป็นความจริงวิธีเดียวที่เหมาะสมในการระบุข้อผิดพลาดในตัวสร้างคือการเพิ่มข้อยกเว้น นั่นคือเหตุผลที่ใน C ++ และในภาษาเชิงวัตถุอื่น ๆ ที่ได้รับการออกแบบโดยคำนึงถึงความปลอดภัยเป็นหลักตัวทำลายจะไม่ถูกเรียกหากมีข้อยกเว้นเกิดขึ้นในตัวสร้างของวัตถุ (หมายความว่าการเริ่มต้นของวัตถุไม่สมบูรณ์) กรณีนี้มักไม่เกิดขึ้นในภาษาสคริปต์เช่น Python ตัวอย่างเช่นรหัสต่อไปนี้จะพ่น AttributeError หาก socket.connect () ล้มเหลว:

class NetworkInterface:
    def __init__(self, address)
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket.connect(address)
        self.stream = self.socket.makefile()

    def __del__(self)
        self.stream.close()
        self.socket.close()

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


คำตอบนี้มีประโยชน์จริงๆ ไม่ใช่แค่การพูดถึง "ไฟเขียว" แต่กล่าวถึงตัวอย่างด้วย "ผู้ทำลาย"
lpapp

รหัส python ของคุณล้มเหลว__del__เนื่องจากเขียนไม่ดี คุณจะมีปัญหาเดียวกันthis->p_socket->close()ทุกประการหากคุณทำในตัวทำลายใน C ++ ใน C ++ คุณจะไม่ทำเช่นนั้น - คุณปล่อยให้วัตถุสมาชิกทำลายตัวเอง ทำเช่นเดียวกันใน python
Eric

1
@ Eric ฉันไม่อยากจะมีปัญหาใน c ++ เพราะC ++ ไม่ทำลายวัตถุที่ไม่ได้รับการเริ่มต้นได้อย่างถูกต้อง จริงๆแล้วมันเป็นสำนวนที่พบบ่อยมากใน C ++ ที่จะจัดสรรทรัพยากรในการสร้างและ deallocate พวกเขาในเตาเผา คุณแนะนำว่าอ็อบเจ็กต์สมาชิกทำลายตัวเอง (การยกเลิกการจัดสรรทรัพยากรในตัวทำลาย) - จากนั้นปัญหาเดียวกันนี้เกิดขึ้นเมื่อเขียนคลาสสมาชิก
Seppo Enarvi

11

ฉันไม่เห็นเหตุผลใด ๆ ว่ามันควรจะฟอร์มไม่ดี

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


6

ห้องสมุดมาตรฐานกล่าวว่า:

>>> f = file("notexisting.txt")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IOError: [Errno 2] No such file or directory: 'notexisting.txt'

นอกจากนี้ฉันไม่เห็นเหตุผลจริงๆว่าทำไมมันถึงถูกมองว่าเป็นรูปแบบที่ไม่ดี



2

ฉันเห็นด้วยกับทั้งหมดข้างต้น

ไม่มีวิธีอื่นที่จะส่งสัญญาณว่ามีบางอย่างผิดพลาดในการเริ่มต้นของวัตถุอื่นนอกจากการเพิ่มข้อยกเว้น

ในคลาสโปรแกรมส่วนใหญ่ที่สถานะของคลาสจะขึ้นอยู่กับอินพุตของคลาสนั้นทั้งหมดเราอาจคาดหวังว่า ValueError หรือ TypeError บางประเภทจะถูกเพิ่มขึ้น

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


2

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

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