"วิธีการที่เหมาะสมในการประกาศข้อยกเว้นที่กำหนดเองใน Python สมัยใหม่?"
ไม่เป็นไรเว้นแต่ว่าข้อยกเว้นของคุณจะเป็นข้อยกเว้นที่เฉพาะเจาะจงมากขึ้น:
class MyException(Exception):
pass
หรือดีกว่า (อาจสมบูรณ์แบบ) แทนที่จะpass
ให้ docstring:
class MyException(Exception):
"""Raise for my specific kind of exception"""
คลาสย่อยยกเว้นข้อยกเว้น
จากเอกสาร
Exception
ข้อยกเว้นในตัวทั้งหมดที่ไม่ได้ออกจากระบบมาจากคลาสนี้ ข้อยกเว้นที่ผู้ใช้กำหนดเองควรได้รับมาจากคลาสนี้ด้วย
นั่นหมายความว่าถ้าข้อยกเว้นของคุณเป็นประเภทของข้อยกเว้นเฉพาะเจาะจงมากขึ้น subclass ที่ยกเว้นแทนทั่วไปException
(และผลที่ได้จะเป็นไปได้ว่าคุณยังคงได้รับจากการException
เป็นเอกสารแนะนำ) นอกจากนี้คุณอย่างน้อยสามารถให้ docstring (และไม่ถูกบังคับให้ใช้pass
คำหลัก):
class MyAppValueError(ValueError):
'''Raise when my specific value is wrong'''
ตั้งค่าคุณสมบัติที่คุณสร้างเองด้วยกำหนดเอง __init__
ตั้งค่าคุณสมบัติที่คุณสร้างตัวเองด้วยที่กำหนดเองหลีกเลี่ยงการใช้พจน์เป็นอาร์กิวเมนต์ตำแหน่งผู้ใช้รหัสของคุณในอนาคตจะขอบคุณ หากคุณใช้แอตทริบิวต์ข้อความที่เลิกใช้แล้วการกำหนดด้วยตัวคุณเองจะเป็นการหลีกเลี่ยงDeprecationWarning
:
class MyAppValueError(ValueError):
'''Raise when a specific subset of values in context of app is wrong'''
def __init__(self, message, foo, *args):
self.message = message # without this you may get DeprecationWarning
# Special attribute you desire with your Error,
# perhaps the value that caused the error?:
self.foo = foo
# allow users initialize misc. arguments as any other builtin Error
super(MyAppValueError, self).__init__(message, foo, *args)
ไม่จำเป็นต้องเขียนของคุณเองจริงๆ __str__
__repr__
หรือ สิ่งที่มีในตัวนั้นดีมากและการสืบทอดแบบมีส่วนร่วมของคุณจะทำให้แน่ใจได้ว่าคุณจะใช้มัน
คำติชมของคำตอบด้านบน
บางทีฉันอาจพลาดคำถาม แต่ทำไมไม่:
class MyException(Exception):
pass
อีกครั้งปัญหาเกี่ยวกับข้างต้นคือการที่จะจับมันคุณจะต้องตั้งชื่อโดยเฉพาะ (นำเข้าถ้าสร้างที่อื่น) หรือตรวจจับข้อยกเว้น (แต่คุณอาจไม่พร้อมที่จะจัดการกับข้อยกเว้นทุกประเภท และคุณควรตรวจจับข้อยกเว้นที่คุณเตรียมไว้เท่านั้น) คำวิจารณ์ที่คล้ายกันกับด้านล่าง แต่ยังไม่ใช่วิธีการเริ่มต้นผ่านทางsuper
และคุณจะได้รับDeprecationWarning
หากคุณเข้าถึงแอตทริบิวต์ข้อความ:
แก้ไข: เพื่อแทนที่บางสิ่ง (หรือผ่าน args พิเศษ) ทำสิ่งนี้:
class ValidationError(Exception):
def __init__(self, message, errors):
# Call the base class constructor with the parameters it needs
super(ValidationError, self).__init__(message)
# Now for your custom code...
self.errors = errors
ด้วยวิธีนี้คุณสามารถส่งผ่านข้อความแสดงข้อผิดพลาดไปยังพารามิเตอร์ที่สองและไปที่ e.errors ในภายหลัง
นอกจากนี้ยังต้องมีการส่งผ่านข้อโต้แย้งสองประการ (นอกเหนือจากself
.) ไม่มากไม่น้อย นั่นเป็นข้อ จำกัด ที่น่าสนใจที่ผู้ใช้ในอนาคตอาจไม่พอใจ
ที่จะตรง - มันละเมิด Liskov ทดแทน
ฉันจะแสดงข้อผิดพลาดทั้งสอง:
>>> ValidationError('foo', 'bar', 'baz').message
Traceback (most recent call last):
File "<pyshell#10>", line 1, in <module>
ValidationError('foo', 'bar', 'baz').message
TypeError: __init__() takes exactly 3 arguments (4 given)
>>> ValidationError('foo', 'bar').message
__main__:1: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
'foo'
เปรียบเทียบกับ:
>>> MyAppValueError('foo', 'FOO', 'bar').message
'foo'