"Cara yang tepat untuk mendeklarasikan pengecualian khusus dengan Python modern?"
Ini baik-baik saja, kecuali pengecualian Anda benar-benar jenis pengecualian yang lebih spesifik:
class MyException(Exception):
pass
Atau lebih baik (mungkin sempurna), daripada pass
memberikan docstring:
class MyException(Exception):
"""Raise for my specific kind of exception"""
Subkelas Pengecualian Subkelas
Dari dokumen
Exception
Semua pengecualian built-in, non-sistem keluar dari kelas ini. Semua pengecualian yang ditentukan pengguna juga harus diturunkan dari kelas ini.
Itu berarti bahwa jika pengecualian Anda adalah jenis pengecualian yang lebih spesifik, subkelas pengecualian itu daripada generik Exception
(dan hasilnya adalah Anda masih berasal dari Exception
seperti yang direkomendasikan oleh dokumen). Juga, Anda setidaknya dapat memberikan dokumen (dan tidak dipaksa untuk menggunakanpass
kata kunci):
class MyAppValueError(ValueError):
'''Raise when my specific value is wrong'''
Tetapkan atribut yang Anda buat sendiri dengan kustom __init__
. Hindari melewatkan dikt sebagai argumen posisional, pengguna masa depan kode Anda akan berterima kasih. Jika Anda menggunakan atribut pesan yang tidak digunakan lagi, menetapkannya sendiri akan menghindari 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)
Benar-benar tidak perlu menulis sendiri __str__
atau__repr__
. Yang builtin sangat bagus, dan warisan koperasi Anda memastikan bahwa Anda menggunakannya.
Kritik atas jawaban teratas
Mungkin saya melewatkan pertanyaan itu, tetapi mengapa tidak:
class MyException(Exception):
pass
Sekali lagi, masalah dengan hal di atas adalah bahwa untuk menangkapnya, Anda harus menyebutkannya secara khusus (mengimpornya jika dibuat di tempat lain) atau menangkap Pengecualian, (tetapi Anda mungkin tidak siap untuk menangani semua jenis Pengecualian, dan Anda seharusnya hanya menangkap pengecualian yang siap Anda tangani). Kritik serupa dengan yang di bawah ini, tetapi juga bukan cara untuk menginisialisasi melalui super
, dan Anda akan mendapatkan DeprecationWarning
jika Anda mengakses atribut pesan:
Edit: untuk mengganti sesuatu (atau memberikan argumen tambahan), lakukan ini:
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
Dengan begitu Anda bisa mengirimkan dikt dari pesan kesalahan ke param kedua, dan sampai nanti dengan e.errors
Ini juga membutuhkan tepat dua argumen untuk diteruskan (selain dari self
.) Tidak lebih, tidak kurang. Itu adalah kendala yang menarik yang mungkin tidak dihargai oleh pengguna di masa depan.
Untuk menjadi langsung - itu melanggar substitusi Liskov .
Saya akan menunjukkan kedua kesalahan:
>>> 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'
Dibandingkan dengan:
>>> MyAppValueError('foo', 'FOO', 'bar').message
'foo'