Ketertarikan Anda pada buku baru " Python Pro Secrets " telah meyakinkan kami bahwa kisah kebiasaan Python layak untuk dilanjutkan. Hari ini kami menawarkan untuk membaca tutorial kecil tentang membuat kelas pengecualian kustom (dalam teks - Anda sendiri). Penulis menariknya, sulit untuk tidak setuju dengannya bahwa keuntungan terpenting dari pengecualian adalah kelengkapan dan kejelasan pesan kesalahan. Sebagian kode dari aslinya berupa gambar.
Selamat datang di cat.
Membuat kelas kesalahan Anda sendiri
Python menyediakan kemampuan untuk membuat kelas pengecualian Anda sendiri. Dengan membuat kelas semacam itu, Anda dapat mendiversifikasi desain kelas dalam aplikasi Anda. Kelas kesalahan khusus bisa mencatat kesalahan, memeriksa objek. Kitalah yang mendefinisikan apa yang dilakukan kelas pengecualian, meskipun biasanya kelas khusus hampir tidak dapat melakukan lebih dari sekadar menampilkan pesan.
Secara alami, jenis kesalahan itu sendiri penting, dan kami sering membuat jenis kesalahan sendiri untuk menunjukkan situasi tertentu yang biasanya tidak tercakup pada level Python. Dengan cara ini, pengguna kelas akan tahu persis apa yang terjadi ketika mereka menemukan kesalahan ini.
Artikel ini dibagi menjadi dua bagian. Pertama, kita akan mendefinisikan kelas pengecualian dengan sendirinya. Kami kemudian mendemonstrasikan bagaimana kami dapat mengintegrasikan kelas pengecualian kami sendiri ke dalam program Python kami dan menunjukkan bagaimana kami dapat meningkatkan kegunaan kelas yang kami desain.
Kelas pengecualian khusus MyCustomError
Melempar pengecualian membutuhkan metode
__init__()
dan
__str__()
.
Saat melontarkan pengecualian, kami telah membuat sebuah instance dari pengecualian tersebut dan pada saat yang sama menampilkannya di layar. Mari kita lihat lebih dekat kelas pengecualian khusus kami yang ditunjukkan di bawah ini.
Kelas MyCustomError di atas memiliki dua metode ajaib,
__init__
dan
__str__
, yang secara otomatis dipanggil selama penanganan pengecualian. Metode
Init
dipanggil saat instance dibuat, dan metode dipanggil saat instance
str
ditampilkan. Oleh karena itu, ketika pengecualian dilemparkan, kedua metode ini biasanya dipanggil segera setelah satu sama lain. Pernyataan pengecualian lemparan Python menempatkan program ke dalam status kesalahan.
Dalam daftar argumen metode
__init__
adalah
*args
. Komponen
*args
adalah mode pencocokan pola khusus yang digunakan dalam fungsi dan metode. Ini memungkinkan Anda untuk melewatkan beberapa argumen, dan menyimpan argumen yang diteruskan sebagai tupel, tetapi pada saat yang sama memungkinkan Anda untuk tidak memberikan argumen sama sekali.
Dalam kasus kami, kami dapat mengatakan bahwa jika
MyCustomError
ada argumen yang diteruskan ke konstruktor , maka kami mengambil argumen yang diberikan pertama dan menetapkannya ke atribut
message
dalam objek. Jika tidak ada argumen yang diberikan, maka atribut
message
akan diberi nilai
None
.
Dalam contoh pertama, pengecualian dilempar
MyCustomError
tanpa argumen apa pun, jadi atributnya
message
objek ini diberi nilai
None
. Sebuah metode akan dipanggil
str
dan akan menampilkan pesan 'Pesan MyCustomError telah dimunculkan'.
Pengecualian
MyCustomError
dilempar tanpa argumen apa pun (tanda kurung kosong). Dengan kata lain, desain objek seperti itu terlihat tidak standar. Tapi ini hanyalah dukungan sintaksis yang disediakan dengan Python saat membuat pengecualian.
Dalam contoh kedua,
MyCustomError
ini dilewatkan dengan argumen string 'Kami punya masalah'. Ini ditetapkan sebagai atribut
message
objek dan ditampilkan sebagai pesan kesalahan ketika pengecualian dilemparkan.
Kode untuk kelas pengecualian MyCustomError ada di sini...
class MyCustomError(Exception):
def __init__(self, *args):
if args:
self.message = args[0]
else:
self.message = None
def __str__(self):
print('calling str')
if self.message:
return 'MyCustomError, {0} '.format(self.message)
else:
return 'MyCustomError has been raised'
# MyCustomError
raise MyCustomError('We have a problem')
Kelas CustomIntFloatDic
Kami membuat kamus kami sendiri, yang nilainya hanya dapat berupa bilangan bulat dan angka floating-point.
Mari kita lanjutkan dan tunjukkan cara menyuntikkan kelas kesalahan dengan mudah dan berguna ke dalam program kita sendiri. Untuk memulainya, saya akan menawarkan contoh yang sedikit dibuat-buat. Dalam contoh fiksi ini, saya akan membuat kamus saya sendiri yang hanya dapat menerima bilangan bulat atau bilangan floating point.
Jika pengguna mencoba menentukan tipe data lain sebagai nilai dalam kamus ini, pengecualian akan dilemparkan. Pengecualian ini akan memberikan informasi yang berguna bagi pengguna tentang cara menggunakan kamus ini. Dalam kasus kami, pesan ini langsung memberi tahu pengguna bahwa hanya bilangan bulat atau angka floating point yang dapat ditentukan sebagai nilai dalam kamus ini.
Saat membuat kamus Anda sendiri, perlu diingat bahwa ada dua tempat di mana nilai dapat ditambahkan ke kamus. Pertama, ini bisa terjadi dalam metode init saat membuat objek (pada tahap ini, objek sudah dapat diberi kunci dan nilai), dan kedua, saat menyetel kunci dan nilai secara langsung di kamus. Di kedua tempat ini, Anda perlu menulis kode untuk memastikan bahwa nilainya hanya dapat berupa tipe
int
atau
float
.
Pertama, saya akan mendefinisikan kelas CustomIntFloatDict yang mewarisi dari kelas bawaan
dict
.
dict
dilewatkan dalam daftar argumen, yang diapit tanda kurung dan mengikuti nama kelas
CustomIntFloatDict
.
Jika kelas dibuat instance-nya
CustomIntFloatDict
, selain itu, tidak ada argumen yang diteruskan ke parameter kunci dan nilai, mereka akan disetel ke
None
. Ekspresi tersebut
if
diinterpretasikan sebagai berikut: jika salah satu kuncinya sama
None
, atau nilainya sama
None
, maka metode akan dipanggil dengan objek
get_dict()
, yang akan mengembalikan atribut
empty_dict
; atribut seperti itu pada suatu objek menunjuk ke daftar kosong. Ingatlah bahwa atribut kelas tersedia di semua contoh kelas.
Tujuan dari kelas ini adalah untuk memungkinkan pengguna melewatkan daftar atau tuple dengan kunci dan nilai di dalamnya. Jika pengguna memasukkan daftar atau tuple mencari kunci dan nilai, maka dua set iterable ini akan digabungkan menggunakan fungsi
zip
bahasa Python. Variabel terkait yang menunjuk ke suatu objek
zip
dapat diulangi, dan tupel dapat dibongkar. Dengan mengulangi tupel, saya memeriksa apakah val adalah turunan dari kelas
int
atau
float
. Jika itu
val
bukan milik salah satu kelas ini, saya membuang pengecualian
IntFloatValueError
saya sendiri dan memberikan val sebagai argumen untuk itu.
IntFloatValueError Exception Class
Ketika pengecualian dilemparkan,
IntFloatValueError
kami membuat instance kelas
IntFloatValueError
dan secara bersamaan menampilkannya di layar. Ini berarti metode ajaib
init
dan akan dipanggil
str
.
Nilai yang menyebabkan pengecualian yang dilempar ditetapkan sebagai atribut yang
value
menyertai kelas
IntFloatValueError
. Saat memanggil metode magic str, pengguna menerima pesan kesalahan yang menginformasikan bahwa nilai
init
in
CustomIntFloatDict
tidak valid. Pengguna tahu apa yang harus dilakukan untuk memperbaiki kesalahan ini.
Kelas pengecualian
IntFloatValueError
dan
KeyValueConstructError
Jika tidak ada pengecualian dilempar, itu saja
val
dari objek yang dirantai ada tipe
int
atau
float
, kemudian mereka akan disetel menggunakan
__setitem__()
, dan metode dari kelas induk akan melakukan segalanya untuk kita
dict
, seperti yang ditunjukkan di bawah ini.
Kelas KeyValueConstructError
Apa yang terjadi jika pengguna memasukkan jenis yang bukan daftar atau tuple kunci dan nilai?
Sekali lagi, contoh ini sedikit artifisial, tetapi berguna untuk menunjukkan kepada Anda bagaimana Anda dapat menggunakan kelas pengecualian Anda sendiri.
Jika pengguna tidak menentukan kunci dan nilai sebagai daftar atau tuple, pengecualian akan dilempar
KeyValueConstructError
. Tujuan dari pengecualian ini adalah untuk memberi tahu pengguna bahwa untuk menulis kunci dan nilai ke suatu objek
CustomIntFloatDict
, daftar atau tuple harus ditentukan dalam konstruktor
init
kelas
CustomIntFloatDict
.
Dalam contoh di atas, sebagai argumen kedua untuk konstruktor
init
banyak hal telah berlalu dan pengecualian dilemparkan karena ini
KeyValueConstructError
. Manfaat dari pesan kesalahan yang ditampilkan adalah bahwa pesan kesalahan yang ditampilkan memberi tahu pengguna bahwa kunci dan nilai yang akan dimasukkan harus dilaporkan sebagai daftar atau tupel.
Sekali lagi, saat pengecualian dilemparkan, instance KeyValueConstructError dibuat, dan kunci serta nilai diteruskan sebagai argumen ke konstruktor KeyValueConstructError. Mereka ditetapkan sebagai nilai atribut kunci dan nilai KeyValueConstructError dan digunakan dalam metode __str__ untuk menghasilkan pesan kesalahan yang berarti saat pesan ditampilkan di layar.
Lebih lanjut, saya bahkan menyertakan tipe data yang melekat dalam objek yang ditambahkan ke konstruktor
init
- Saya melakukan ini untuk kejelasan.
Menyetel kunci dan nilai di CustomIntFloatDict
CustomIntFloatDict
mewarisi dari
dict
. Artinya, ia akan berfungsi persis seperti kamus, kecuali di tempat yang kita pilih untuk mengubah perilakunya secara selektif.
__setitem__
Adalah metode ajaib yang dipanggil saat mengatur kunci dan nilai dalam kamus. Dalam implementasi kami,
setitem
kami memeriksa bahwa nilainya bertipe
int
atau
float
, dan hanya setelah pemeriksaan berhasil, nilai tersebut dapat disetel dalam kamus. Jika pemeriksaan gagal, Anda dapat menggunakan kelas pengecualian lagi
IntFloatValueError
. Di sini Anda dapat memastikan bahwa jika kami mencoba menetapkan string
โbad_valueโ
sebagai nilai dalam kamus
test_4
, kami akan mendapatkan pengecualian.
Semua kode untuk tutorial ini ditampilkan di bawah ini dan diposting di Github .
# , int float
class IntFloatValueError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return '{} is invalid input, CustomIntFloatDict can only accept ' \
'integers and floats as its values'.format(self.value)
class KeyValueContructError(Exception):
def __init__(self, key, value):
self.key = key
self.value = value
def __str__(self):
return 'keys and values need to be passed as either list or tuple' + '\n' + \
' {} is of type: '.format(self.key) + str(type(self.key)) + '\n' + \
' {} is of type: '.format(self.value) + str(type(self.value))
class CustomIntFloatDict(dict):
empty_dict = {}
def __init__(self, key=None, value=None):
if key is None or value is None:
self.get_dict()
elif not isinstance(key, (tuple, list,)) or not isinstance(value, (tuple, list)):
raise KeyValueContructError(key, value)
else:
zipped = zip(key, value)
for k, val in zipped:
if not isinstance(val, (int, float)):
raise IntFloatValueError(val)
dict.__setitem__(self, k, val)
def get_dict(self):
return self.empty_dict
def __setitem__(self, key, value):
if not isinstance(value, (int, float)):
raise IntFloatValueError(value)
return dict.__setitem__(self, key, value)
#
# test_1 = CustomIntFloatDict()
# print(test_1)
# test_2 = CustomIntFloatDict({'a', 'b'}, [1, 2])
# print(test_2)
# test_3 = CustomIntFloatDict(('x', 'y', 'z'), (10, 'twenty', 30))
# print(test_3)
# test_4 = CustomIntFloatDict(('x', 'y', 'z'), (10, 20, 30))
# print(test_4)
# test_4['r'] = 1.3
# print(test_4)
# test_4['key'] = 'bad_value'
Kesimpulan
Jika Anda membuat pengecualian sendiri, bekerja dengan kelas menjadi jauh lebih nyaman. Kelas pengecualian harus memiliki metode ajaib
init
dan
str
yang secara otomatis dipanggil selama penanganan pengecualian. Terserah Anda apa yang akan dilakukan kelas pengecualian Anda sendiri. Di antara metode yang ditampilkan adalah metode yang bertanggung jawab untuk memeriksa objek dan menampilkan pesan kesalahan informatif di layar.
Bagaimanapun, kelas pengecualian membuatnya lebih mudah untuk menangani kesalahan yang muncul!