Deskriptor Python atau secara umum, deskriptor, memberi Anda teknik yang kuat untuk menulis kode yang dapat digunakan kembali dan dibagikan antar kelas. Sekilas mirip dengan konsep pewarisan, tetapi secara teknis berbeda. Ini adalah cara serbaguna untuk mencegat akses atribut. Deskriptor adalah mekanisme di balik properti, metode statis, metode kelas, metode super, dan sebagainya.
Deskriptor ditambahkan pada Python versi 2.2, dan sejak itu dianggap sebagai hal “magis” yang memberi gaya baru pada kelas tradisional. Ini adalah kelas yang memungkinkan Anda mengelola properti di kelas lain. Secara khusus, mereka mengimplementasikan antarmuka untuk metode __get__(), __set__() dan __delete__() yang membuatnya menarik karena banyak alasan. Misalnya, dekorator kelas dan dekorator properti yang mungkin sudah Anda lihat di Python.
Sederhananya, kelas yang mengimplementasikan metode __get__(), __set()__, atau __delete()__ untuk suatu objek dikenal sebagai "Descriptor". Mengutip langsung dari dokumentasi resmi Python, deskriptor adalah atribut objek dengan perilaku binding, yaitu akses atributnya digantikan oleh metode dalam protokol deskriptor. Metode-metode tersebut adalah __get__(), __set__(), dan __delete__() (Sumber).
Perilaku binding dalam konteks deskriptor berarti pengikatan cara nilai dapat diatur (set), diambil (get), atau dihapus untuk variabel, objek, atau sekumpulan data tertentu. Seluruh interaksi ini terikat ke potongan data tersebut karena hanya berlaku pada data yang Anda tetapkan, sehingga mengikatnya pada bagian data tertentu itu saja.
Deskriptor dapat dikategorikan lebih lanjut menjadi deskriptor data dan non-data. Jika deskriptor yang Anda tulis hanya memiliki metode __get__(), maka itu adalah deskriptor non-data; sebaliknya, implementasi yang melibatkan metode __set__() dan __delete__() disebut deskriptor data. Deskriptor non-data hanya dapat dibaca, sedangkan deskriptor data dapat dibaca dan ditulis.
Penting untuk dicatat bahwa deskriptor ditetapkan pada kelas, bukan pada instans kelas. Memodifikasi kelas akan menimpa atau menghapus deskriptor itu sendiri, alih-alih memicu kodenya (IBM Developer).
Pada akhirnya, kelas deskriptor tidak terbatas hanya memiliki tiga metode ini, artinya ia juga dapat memuat atribut lain selain metode get, set, dan delete.
Mari pahami metode get, set, dan delete lebih rinci yang terinspirasi dari halaman IBM Developer ini:
self adalah instans deskriptor yang Anda buat (Real Python).
object adalah instans objek tempat deskriptor Anda terpasang (Real Python).
type adalah tipe objek tempat deskriptor terpasang (Real Python).
value adalah nilai yang ditetapkan ke atribut deskriptor. get(self, object, type) set(self, object, value) delete(self, object)
__get__() mengakses atribut atau saat Anda ingin mengekstrak informasi. Mengembalikan nilai atribut atau memunculkan pengecualian AttributeError jika atribut yang diminta tidak ada.
__set__() dipanggil pada operasi penetapan atribut yang menetapkan nilai suatu atribut. Tidak mengembalikan apa pun, tetapi dapat memunculkan pengecualian AttributeError.
__delete__() mengontrol operasi penghapusan, yaitu saat Anda ingin menghapus atribut dari suatu objek. Tidak mengembalikan apa pun.
Sekarang mari pahami tujuan Deskriptor dengan bantuan beberapa contoh!
Tujuan Deskriptor
Misalkan kita mendefinisikan kelas car yang memiliki tiga atribut, yaitu make, model, dan fuel_cap. Anda akan menggunakan metode __init__() untuk menginisialisasi atribut kelas. Lalu, Anda akan menggunakan fungsi magis __str__(), yang hanya akan mengembalikan keluaran dari tiga atribut yang Anda berikan ke kelas saat membuat objek.
Perhatikan bahwa metode __str__() mengembalikan representasi string dari objek. Ini dipanggil ketika fungsi print() atau str() dipanggil pada objek kelas.
classCar:def__init__(self,make,model,fuel_cap):
self.make = make
self.model = model
self.fuel_cap = fuel_cap
def__str__(self):return"{0} model {1} with a fuel capacity of {2} ltr.".format(self.make,self.model,self.fuel_cap)Didukung oleh
BMW model X7with a fuel capacity of-40 ltr.Didukung oleh
Tunggu dulu, ada yang tidak beres, bukan? Kapasitas bahan bakar mobil tidak mungkin negatif. Namun, Python menerimanya sebagai masukan tanpa error. Ini karena Python adalah bahasa pemrograman dinamis yang tidak mendukung pemeriksaan tipe secara eksplisit.
Untuk menghindari masalah ini, mari tambahkan kondisi if di metode __init__() dan periksa apakah kapasitas bahan bakar yang dimasukkan valid atau tidak. Jika tidak valid, naikkan pengecualian ValueError.
classCar:def__init__(self,make,model,fuel_cap):
self.make = make
self.model = model
self.fuel_cap = fuel_cap
if self.fuel_cap <0:raise ValueError("Fuel Capacity can never be less than zero")def__str__(self):return"{0} model {1} with a fuel capacity of {2} ltr.".format(self.make,self.model,self.fuel_cap)Didukung oleh
----------------------------------------ValueErrorTraceback(most recent call last)<ipython-input-22-1c3d23be72f7>in<module>---->1 car2 =Car("BMW","X7",-40)2print(car2)<ipython-input-20-1e154783588d>in__init__(self, make, model, fuel_cap)5 self.fuel_cap = fuel_cap
6if self.fuel_cap <0:---->7 raise ValueError("Fuel Capacity can never be less than zero")89 def __str__(self):ValueError: Fuel Capacity can never be less than zero
Didukung oleh
Dari keluaran di atas, Anda dapat melihat bahwa untuk saat ini semuanya berjalan baik karena program menaikkan ValueError jika kapasitas bahan bakar di bawah nol.
Namun, bisa ada masalah lain, yaitu bagaimana jika fuel capacity yang dimasukkan berupa nilai float atau string. Bukan hanya kapasitas bahan bakar, tetapi juga make dan model mobil bisa berupa nilai integer. Dalam semua kasus ini, program tidak akan menaikkan pengecualian.
classCar:def__init__(self,make,model,fuel_cap):
self.make = make
self.model = model
self.fuel_cap = fuel_cap
if self.fuel_cap <0:raise ValueError("Fuel Capacity can never be less than zero")def__str__(self):return"{0} model {1} with a fuel capacity of {2} ltr.".format(self.make,self.model,self.fuel_cap)Didukung oleh
-40 model X7with a fuel capacity of40 ltr.Didukung oleh
Untuk menangani kasus di atas, Anda mungkin terpikir menambahkan kondisi if lain atau menggunakan metode isinstance untuk pemeriksaan tipe.
Kali ini mari gunakan metode bawaan isinstance untuk menangani error.
classCar:def__init__(self,make,model,fuel_cap):
self.make = make
self.model = model
self.fuel_cap = fuel_cap
ifisinstance(self.make,str):print(self.make)else:raise ValueError("Make of the car can never be an integer")if self.fuel_cap <0:raise ValueError("Fuel Capacity can never be less than zero")def__str__(self):return"{0} model {1} with a fuel capacity of {2} ltr.".format(self.make,self.model,self.fuel_cap)Didukung oleh
----------------------------------------ValueErrorTraceback(most recent call last)<ipython-input-34-75b08cba454f>in<module>---->1 car2 =Car(-40,"X7",40)2print(car2)<ipython-input-31-175690bf3b98>in__init__(self, make, model, fuel_cap)7print(self.make)8else:---->9 raise ValueError("Make of the car can never be an integer")1011if self.fuel_cap <0:ValueError: Make of the car can never be an integer
Didukung oleh
Bagus! Jadi Anda juga berhasil menangani error ini.
Namun, bagaimana jika Anda ingin mengubah atribut kapasitas bahan bakar menjadi negatif 40 secara eksplisit di kemudian hari. Dalam kasus ini, tidak akan berhasil, karena pemeriksaan tipe hanya dilakukan sekali di metode __init__(). Seperti Anda tahu, metode __init__() adalah konstruktor dan dipanggil hanya sekali saat Anda membuat objek dari kelas. Maka, pemeriksaan tipe kustom akan gagal di kemudian hari.
Mari pahami dengan contoh.
classCar:def__init__(self,make,model,fuel_cap):
self.make = make
self.model = model
self.fuel_cap = fuel_cap
ifisinstance(self.make,str):print(self.make)else:raise ValueError("Make of the car can never be an integer")if self.fuel_cap <0:raise ValueError("Fuel Capacity can never be less than zero")def__str__(self):return"{0} model {1} with a fuel capacity of {2} ltr.".format(self.make,self.model,self.fuel_cap)Didukung oleh
-40 model X7with a fuel capacity of40 ltr.Didukung oleh
Nah, itu dia! Anda berhasil keluar dari pemeriksaan tipe.
Sekarang pikirkan begini, bagaimana jika Anda memiliki banyak atribut lain dari mobil seperti jarak tempuh, harga, aksesori, dan sebagainya yang juga membutuhkan pemeriksaan tipe, dan Anda juga menginginkan fungsionalitas di mana beberapa atribut hanya memiliki akses baca. Bukankah itu akan sangat merepotkan?
Untuk mengatasi semua masalah di atas, Python memiliki Deskriptor yang menjadi penyelamat!
Seperti yang Anda pelajari di atas, kelas apa pun yang mengimplementasikan metode magis __get__(), __set()__, atau __delete()__ untuk objek protokol deskriptor disebut Deskriptor. Mereka juga memberi Anda kontrol tambahan atas cara sebuah atribut bekerja, misalnya apakah atribut tersebut seharusnya bisa dibaca atau ditulis.
Sekarang mari perluas contoh di atas dengan menambahkan metode Python Descriptor.
classDescriptor:def__init__(self):
self.__fuel_cap =0def__get__(self, instance, owner):return self.__fuel_cap
def__set__(self, instance, value):ifisinstance(value,int):print(value)else:raise TypeError("Fuel Capacity can only be an integer")if value <0:raise ValueError("Fuel Capacity can never be less than zero")
self.__fuel_cap = value
def__delete__(self, instance):del self.__fuel_cap
Didukung oleh
classCar:
fuel_cap = Descriptor()def__init__(self,make,model,fuel_cap):
self.make = make
self.model = model
self.fuel_cap = fuel_cap
def__str__(self):return"{0} model {1} with a fuel capacity of {2} ltr.".format(self.make,self.model,self.fuel_cap)Didukung oleh
40BMW model X7with a fuel capacity of40 ltr.Didukung oleh
Jangan khawatir jika kelas Descriptor terlihat membingungkan. Mari kita uraikan menjadi bagian-bagian kecil dan pahami apa yang dilakukan masing-masing metode.
Metode __init__() dari kelas Descriptor memiliki variabel lokal __fuel_cap bernilai nol. dunder atau dua garis bawah di awal artinya variabel tersebut privat. Dunder di awal hanya untuk membedakan atribut kapasitas bahan bakar milik kelas Descriptor dengan kelas Car.
Seperti yang kini Anda tahu, metode __get__() digunakan untuk mengambil atribut, dan ia mengembalikan variabel kapasitas bahan bakar. Ia menerima tiga argumen: objek deskriptor, instans kelas yang memuat instans objek deskriptor, yaitu car2, dan terakhir pemilik (owner), yaitu kelas tempat instans tersebut berada, yaitu kelas Car. Dalam metode ini, Anda cukup mengembalikan atribut nilai, yaitu fuel_cap yang nilainya diatur dalam metode __set__().
Metode __set__() dipanggil ketika nilai diatur pada atribut, dan tidak seperti metode __get__(), ia tidak mengembalikan apa pun. Ia memiliki dua argumen selain objek deskriptor itu sendiri, yaitu instans yang sama seperti pada metode __get__() dan argumen value, yaitu nilai yang Anda tetapkan pada atribut. Dalam metode ini, Anda memeriksa apakah nilai yang ingin ditetapkan ke atribut fuel_cap adalah integer atau bukan. Jika bukan, Anda menaikkan pengecualian TypeError. Lalu, dalam metode yang sama, Anda juga memeriksa apakah nilainya kurang dari nol; jika ya, Anda menaikkan pengecualian lain, kali ini ValueError. Setelah memeriksa error, Anda memperbarui atribut fuel_cap sama dengan nilai tersebut.
Terakhir, metode __delete__(), yang dipanggil saat atribut dihapus dari suatu objek, dan seperti metode __set__(), ia tidak mengembalikan apa pun.
Kelas Car tetap sama seperti sebelumnya. Namun, satu-satunya perubahan yang Anda lakukan adalah menambahkan instans fuel_cap dari kelas Descriptor(). Perhatikan bahwa seperti disebutkan sebelumnya, instans kelas deskriptor harus ditambahkan ke kelas sebagai atribut kelas, bukan sebagai atribut instans.
Begitu Anda menetapkan variabel lokal fuel_cap di metode __init__() ke instans fuel_cap, itu akan memanggil metode __set__() dari kelas Descriptor.
Sekarang mari ubah kapasitas bahan bakar menjadi nilai negatif dan lihat apakah program menaikkan pengecualian ValueError atau tidak.
-40----------------------------------------ValueErrorTraceback(most recent call last)<ipython-input-115-1c3d23be72f7>in<module>---->1 car2 =Car("BMW","X7",-40)2print(car2)<ipython-input-107-3e1f3e97d3c7>in__init__(self, make, model, fuel_cap)4 self.make = make
5 self.model = model
---->6 self.fuel_cap = fuel_cap
78 def __str__(self):<ipython-input-106-0b252695aeed>in__set__(self, instance, value)1112if value <0:--->13 raise ValueError("Fuel Capacity can never be less than zero")1415 self.__fuel_cap = value
ValueError: Fuel Capacity can never be less than zero
Didukung oleh
Jika Anda ingat di sini, pemeriksaan tipe gagal ketika Anda kemudian mengubah nilai atribut menjadi angka negatif karena pemeriksaan tipe hanya berlaku sekali di metode __init__(). Mari perbarui nilai fuel_cap menjadi nilai string dan lihat apakah ini menghasilkan error.
-1----------------------------------------ValueErrorTraceback(most recent call last)<ipython-input-120-dea9dbe96ebe>in<module>---->1 car2.fuel_cap =-1<ipython-input-106-0b252695aeed>in__set__(self, instance, value)1112if value <0:--->13 raise ValueError("Fuel Capacity can never be less than zero")1415 self.__fuel_cap = value
ValueError: Fuel Capacity can never be less than zero
Didukung oleh
----------------------------------------TypeErrorTraceback(most recent call last)<ipython-input-121-0b316a9872c6>in<module>---->1 car2.fuel_cap ="BMW"<ipython-input-106-0b252695aeed>in__set__(self, instance, value)8print(value)9else:--->10 raise TypeError("Fuel Capacity can only be an integer")1112if value <0:TypeError: Fuel Capacity can only be an integer
Didukung oleh
Sempurna! Seperti yang Anda lihat, ini berfungsi ketika Anda memperbarui atribut kapasitas bahan bakar di kemudian hari.
Ada sedikit masalah pada Deskriptor, yaitu saat Anda membuat instans baru atau instans kedua dari kelas, nilai instans sebelumnya tertimpa. Alasannya karena Deskriptor ditautkan ke kelas, bukan ke instans.
Mari pahami dengan contoh di bawah ini.
car3 = Car("BMW","X7",48)#created a new instance 'car3' with different valuesDidukung oleh
BMW model X7with a fuel capacity of48 ltr.Didukung oleh
Kesimpulan
Selamat telah menyelesaikan tutorial ini.
Tutorial ini ditujukan bagi mereka yang sudah nyaman dengan Python dan bercita-cita menguasai tingkat lanjut. Sebagai latihan yang baik, Anda mungkin ingin mencari cara untuk mengatasi masalah penimpaan instans yang dibahas dalam tutorial hari ini.
Jangan ragu untuk mengajukan pertanyaan terkait tutorial ini di kolom komentar di bawah.
Jika Anda ingin mempelajari lebih lanjut tentang Python, ikuti jalur keterampilan lengkap Python Programming dari DataCamp.
Temukan alasan mengapa Anda sebaiknya (tidak) menggunakan spaghetti plot untuk menyampaikan ketidakpastian jalur prediksi badai serta dampaknya terhadap interpretasi.
Kuasai pertanyaan wawancara basis data, dari konsep SQL dasar hingga skenario desain sistem tingkat lanjut. Panduan mendalam ini mencakup semua yang Anda perlukan untuk sukses di wawancara DBMS dan meraih peran berikutnya.
Selami ilmu data dengan Python dan pelajari cara menganalisis serta memvisualisasikan data Anda secara efektif. Tak perlu pengalaman atau keterampilan coding.
Deskriptor Python atau secara umum, deskriptor, memberi Anda teknik yang kuat untuk menulis kode yang dapat digunakan kembali dan dibagikan antar kelas. Sekilas mirip dengan konsep pewarisan, tetapi secara teknis berbeda. Ini adalah cara serbaguna untuk mencegat akses atribut. Deskriptor adalah mekanisme di balik properti, metode statis, metode kelas, metode super, dan sebagainya.
Deskriptor ditambahkan pada Python versi 2.2, dan sejak itu dianggap sebagai hal “magis” yang memberi gaya baru pada kelas tradisional. Ini adalah kelas yang memungkinkan Anda mengelola properti di kelas lain. Secara khusus, mereka mengimplementasikan antarmuka untuk metode
__get__(),__set__()dan__delete__()yang membuatnya menarik karena banyak alasan. Misalnya, dekorator kelas dan dekorator properti yang mungkin sudah Anda lihat di Python.Sederhananya, kelas yang mengimplementasikan metode
__get__(),__set()__, atau__delete()__untuk suatu objek dikenal sebagai "Descriptor". Mengutip langsung dari dokumentasi resmi Python, deskriptor adalah atribut objek denganperilaku binding, yaitu akses atributnya digantikan oleh metode dalam protokol deskriptor. Metode-metode tersebut adalah__get__(),__set__(), dan__delete__()(Sumber).Perilaku bindingdalam konteks deskriptor berarti pengikatan cara nilai dapat diatur (set), diambil (get), atau dihapus untuk variabel, objek, atau sekumpulan data tertentu. Seluruh interaksi initerikatke potongan data tersebut karena hanya berlaku pada data yang Anda tetapkan, sehingga mengikatnya pada bagian data tertentu itu saja.Deskriptor dapat dikategorikan lebih lanjut menjadi deskriptor data dan non-data. Jika deskriptor yang Anda tulis hanya memiliki metode
__get__(), maka itu adalah deskriptor non-data; sebaliknya, implementasi yang melibatkan metode__set__()dan__delete__()disebut deskriptor data. Deskriptor non-data hanya dapat dibaca, sedangkan deskriptor data dapat dibaca dan ditulis.Penting untuk dicatat bahwa deskriptor ditetapkan pada kelas, bukan pada instans kelas. Memodifikasi kelas akan menimpa atau menghapus deskriptor itu sendiri, alih-alih memicu kodenya (IBM Developer).
Pada akhirnya, kelas deskriptor tidak terbatas hanya memiliki tiga metode ini, artinya ia juga dapat memuat atribut lain selain metode
get,set, dandelete.Mari pahami metode
get,set, dandeletelebih rinci yang terinspirasi dari halaman IBM Developer ini:selfadalah instans deskriptor yang Anda buat (Real Python).objectadalah instans objek tempat deskriptor Anda terpasang (Real Python).typeadalah tipe objek tempat deskriptor terpasang (Real Python).valueadalah nilai yang ditetapkan ke atribut deskriptor. get(self, object, type) set(self, object, value) delete(self, object)__get__()mengakses atribut atau saat Anda ingin mengekstrak informasi. Mengembalikan nilai atribut atau memunculkan pengecualian AttributeError jika atribut yang diminta tidak ada.__set__()dipanggil pada operasi penetapan atribut yang menetapkan nilai suatu atribut. Tidak mengembalikan apa pun, tetapi dapat memunculkan pengecualian AttributeError.__delete__()mengontrol operasi penghapusan, yaitu saat Anda ingin menghapus atribut dari suatu objek. Tidak mengembalikan apa pun.Sekarang mari pahami tujuan Deskriptor dengan bantuan beberapa contoh!
Tujuan Deskriptor
Misalkan kita mendefinisikan kelas
caryang memiliki tiga atribut, yaitumake,model, danfuel_cap. Anda akan menggunakan metode__init__()untuk menginisialisasi atribut kelas. Lalu, Anda akan menggunakan fungsi magis__str__(), yang hanya akan mengembalikan keluaran dari tiga atribut yang Anda berikan ke kelas saat membuat objek.Perhatikan bahwa metode
__str__()mengembalikan representasi string dari objek. Ini dipanggil ketika fungsiprint()ataustr()dipanggil pada objek kelas.Seperti yang terlihat dari keluaran di atas, semuanya terlihat baik!
Sekarang mari ubah kapasitas bahan bakar mobil menjadi negatif 40.
Tunggu dulu, ada yang tidak beres, bukan? Kapasitas bahan bakar mobil tidak mungkin negatif. Namun, Python menerimanya sebagai masukan tanpa error. Ini karena Python adalah bahasa pemrograman dinamis yang tidak mendukung pemeriksaan tipe secara eksplisit.
Untuk menghindari masalah ini, mari tambahkan kondisi
ifdi metode__init__()dan periksa apakah kapasitas bahan bakar yang dimasukkan valid atau tidak. Jika tidak valid, naikkan pengecualian ValueError.Dari keluaran di atas, Anda dapat melihat bahwa untuk saat ini semuanya berjalan baik karena program menaikkan
ValueErrorjika kapasitas bahan bakar di bawah nol.Namun, bisa ada masalah lain, yaitu bagaimana jika
fuel capacityyang dimasukkan berupa nilai float atau string. Bukan hanya kapasitas bahan bakar, tetapi jugamakedanmodelmobil bisa berupa nilai integer. Dalam semua kasus ini, program tidak akan menaikkan pengecualian.Untuk menangani kasus di atas, Anda mungkin terpikir menambahkan kondisi
iflain atau menggunakan metodeisinstanceuntuk pemeriksaan tipe.Kali ini mari gunakan metode bawaan
isinstanceuntuk menangani error.Bagus! Jadi Anda juga berhasil menangani error ini.
Namun, bagaimana jika Anda ingin mengubah atribut kapasitas bahan bakar menjadi negatif 40 secara eksplisit di kemudian hari. Dalam kasus ini, tidak akan berhasil, karena pemeriksaan tipe hanya dilakukan sekali di metode
__init__(). Seperti Anda tahu, metode__init__()adalah konstruktor dan dipanggil hanya sekali saat Anda membuat objek dari kelas. Maka, pemeriksaan tipe kustom akan gagal di kemudian hari.Mari pahami dengan contoh.
Nah, itu dia! Anda berhasil keluar dari pemeriksaan tipe.
Sekarang pikirkan begini, bagaimana jika Anda memiliki banyak atribut lain dari mobil seperti jarak tempuh, harga, aksesori, dan sebagainya yang juga membutuhkan pemeriksaan tipe, dan Anda juga menginginkan fungsionalitas di mana beberapa atribut hanya memiliki akses
baca. Bukankah itu akan sangat merepotkan?Untuk mengatasi semua masalah di atas, Python memiliki Deskriptor yang menjadi penyelamat!
Seperti yang Anda pelajari di atas, kelas apa pun yang mengimplementasikan metode magis
__get__(),__set()__, atau__delete()__untuk objek protokol deskriptor disebut Deskriptor. Mereka juga memberi Anda kontrol tambahan atas cara sebuah atribut bekerja, misalnya apakah atribut tersebut seharusnya bisa dibaca atau ditulis.Sekarang mari perluas contoh di atas dengan menambahkan metode Python Descriptor.
Jangan khawatir jika kelas Descriptor terlihat membingungkan. Mari kita uraikan menjadi bagian-bagian kecil dan pahami apa yang dilakukan masing-masing metode.
__init__()dari kelas Descriptor memiliki variabel lokal__fuel_capbernilai nol.dunderatau dua garis bawah di awal artinya variabel tersebut privat. Dunder di awal hanya untuk membedakan atribut kapasitas bahan bakar milik kelas Descriptor dengan kelas Car.__get__()digunakan untuk mengambil atribut, dan ia mengembalikan variabel kapasitas bahan bakar. Ia menerima tiga argumen: objek deskriptor, instans kelas yang memuat instans objek deskriptor, yaitucar2, dan terakhir pemilik (owner), yaitu kelas tempat instans tersebut berada, yaitu kelasCar. Dalam metode ini, Anda cukup mengembalikan atribut nilai, yaitufuel_capyang nilainya diatur dalam metode__set__().__set__()dipanggil ketika nilai diatur pada atribut, dan tidak seperti metode__get__(), ia tidak mengembalikan apa pun. Ia memiliki dua argumen selain objek deskriptor itu sendiri, yaitu instans yang sama seperti pada metode__get__()dan argumen value, yaitu nilai yang Anda tetapkan pada atribut. Dalam metode ini, Anda memeriksa apakah nilai yang ingin ditetapkan ke atributfuel_capadalah integer atau bukan. Jika bukan, Anda menaikkan pengecualianTypeError. Lalu, dalam metode yang sama, Anda juga memeriksa apakah nilainya kurang dari nol; jika ya, Anda menaikkan pengecualian lain, kali iniValueError. Setelah memeriksa error, Anda memperbarui atributfuel_capsama dengan nilai tersebut.__delete__(), yang dipanggil saat atribut dihapus dari suatu objek, dan seperti metode__set__(), ia tidak mengembalikan apa pun.Kelas
Cartetap sama seperti sebelumnya. Namun, satu-satunya perubahan yang Anda lakukan adalah menambahkan instansfuel_capdari kelasDescriptor(). Perhatikan bahwa seperti disebutkan sebelumnya, instans kelas deskriptor harus ditambahkan ke kelas sebagai atribut kelas, bukan sebagai atribut instans.Begitu Anda menetapkan variabel lokal
fuel_capdi metode__init__()ke instansfuel_cap, itu akan memanggil metode__set__()dari kelas Descriptor.Sekarang mari ubah kapasitas bahan bakar menjadi nilai negatif dan lihat apakah program menaikkan pengecualian ValueError atau tidak.
Jika Anda ingat di sini, pemeriksaan tipe gagal ketika Anda kemudian mengubah nilai atribut menjadi angka negatif karena pemeriksaan tipe hanya berlaku sekali di metode
__init__(). Mari perbarui nilai fuel_cap menjadi nilai string dan lihat apakah ini menghasilkan error.Sempurna! Seperti yang Anda lihat, ini berfungsi ketika Anda memperbarui atribut kapasitas bahan bakar di kemudian hari.
Ada sedikit masalah pada Deskriptor, yaitu saat Anda membuat instans baru atau instans kedua dari kelas, nilai instans sebelumnya tertimpa. Alasannya karena Deskriptor ditautkan ke kelas, bukan ke instans.
Mari pahami dengan contoh di bawah ini.
Ketika Anda mencetak instans
car2, Anda akan melihat bahwa nilainya telah ditimpa olehcar3.Kesimpulan
Selamat telah menyelesaikan tutorial ini.
Tutorial ini ditujukan bagi mereka yang sudah nyaman dengan Python dan bercita-cita menguasai tingkat lanjut. Sebagai latihan yang baik, Anda mungkin ingin mencari cara untuk mengatasi masalah penimpaan instans yang dibahas dalam tutorial hari ini.
Jangan ragu untuk mengajukan pertanyaan terkait tutorial ini di kolom komentar di bawah.
Jika Anda ingin mempelajari lebih lanjut tentang Python, ikuti jalur keterampilan lengkap Python Programming dari DataCamp.
Lihat juga Tutorial Fungsi Python kami.