Perbedaan antara isinstance()
dan type()
dalam Python?
Ketik memeriksa dengan
isinstance(obj, Base)
memungkinkan untuk instance dari subclass dan beberapa basis yang mungkin:
isinstance(obj, (Base1, Base2))
sedangkan jenis-memeriksa dengan
type(obj) is Base
hanya mendukung jenis yang dirujuk.
Sebagai seorang sidenote, is
kemungkinan lebih tepat daripada
type(obj) == Base
karena kelas adalah lajang.
Hindari pengecekan tipe - gunakan Polimorfisme (ketikan bebek)
Dengan Python, biasanya Anda ingin mengizinkan jenis apa pun untuk argumen Anda, memperlakukannya seperti yang diharapkan, dan jika objek tidak berperilaku seperti yang diharapkan, itu akan menimbulkan kesalahan yang sesuai. Ini dikenal sebagai polimorfisme, juga dikenal sebagai bebek-mengetik.
def function_of_duck(duck):
duck.quack()
duck.swim()
Jika kode di atas berfungsi, kita dapat beranggapan argumen kita adalah bebek. Dengan demikian kita dapat melewati hal-hal lain yang merupakan sub-jenis bebek yang sebenarnya:
function_of_duck(mallard)
atau yang berfungsi seperti bebek:
function_of_duck(object_that_quacks_and_swims_like_a_duck)
dan kode kami masih berfungsi.
Namun, ada beberapa kasus di mana diinginkan untuk secara eksplisit mengetik-cek. Mungkin Anda memiliki hal-hal yang masuk akal untuk dilakukan dengan berbagai jenis objek. Sebagai contoh, objek Dataframe Pandas dapat dibangun dari dikte atau catatan. Dalam kasus seperti itu, kode Anda perlu mengetahui jenis argumen apa yang diperolehnya sehingga dapat menanganinya dengan benar.
Jadi, untuk menjawab pertanyaan:
Perbedaan antara isinstance()
dan type()
dalam Python?
Izinkan saya menunjukkan perbedaannya:
type
Katakanlah Anda perlu memastikan perilaku tertentu jika fungsi Anda mendapatkan jenis argumen tertentu (kasus penggunaan umum untuk konstruktor). Jika Anda memeriksa jenis seperti ini:
def foo(data):
'''accepts a dict to construct something, string support in future'''
if type(data) is not dict:
# we're only going to test for dicts for now
raise ValueError('only dicts are supported for now')
Jika kita mencoba untuk mengirimkan dict yang merupakan subkelas dari dict
(sebagaimana seharusnya kita bisa, jika kita mengharapkan kode kita untuk mengikuti prinsip Substitusi Liskov , subtipe dapat diganti dengan jenis) kode kita rusak !:
from collections import OrderedDict
foo(OrderedDict([('foo', 'bar'), ('fizz', 'buzz')]))
menimbulkan kesalahan!
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in foo
ValueError: argument must be a dict
isinstance
Tetapi jika kita menggunakan isinstance
, kita dapat mendukung Substitusi Liskov !:
def foo(a_dict):
if not isinstance(a_dict, dict):
raise ValueError('argument must be a dict')
return a_dict
foo(OrderedDict([('foo', 'bar'), ('fizz', 'buzz')]))
kembali OrderedDict([('foo', 'bar'), ('fizz', 'buzz')])
Abstrak Kelas Dasar
Bahkan, kita bisa melakukan yang lebih baik lagi. collections
menyediakan Kelas Dasar Abstrak yang memberlakukan protokol minimal untuk berbagai jenis. Dalam kasus kami, jika kami hanya mengharapkan Mapping
protokol, kami dapat melakukan hal berikut, dan kode kami menjadi lebih fleksibel:
from collections import Mapping
def foo(a_dict):
if not isinstance(a_dict, Mapping):
raise ValueError('argument must be a dict')
return a_dict
Tanggapan terhadap komentar:
Perlu dicatat bahwa tipe dapat digunakan untuk memeriksa beberapa kelas yang menggunakan type(obj) in (A, B, C)
Ya, Anda bisa menguji kesetaraan jenis, tetapi alih-alih yang di atas, gunakan beberapa pangkalan untuk aliran kontrol, kecuali Anda secara khusus hanya mengizinkan jenis-jenis itu:
isinstance(obj, (A, B, C))
Perbedaannya, sekali lagi, adalah yang isinstance
mendukung subclass yang dapat diganti untuk orang tua tanpa melanggar program, properti yang dikenal sebagai substitusi Liskov.
Bahkan lebih baik lagi, balikkan dependensi Anda dan jangan periksa untuk tipe tertentu sama sekali.
Kesimpulan
Jadi karena kami ingin mendukung penggantian subclass, dalam kebanyakan kasus, kami ingin menghindari pemeriksaan type
tipe dan lebih memilih pemeriksaan tipe isinstance
- kecuali Anda benar-benar perlu mengetahui kelas yang tepat dari sebuah instance.
str
danunicode
(tempat Anda dapat memeriksabasestring
), Anda dapat menggunakan tuple untuk memeriksa beberapa tipe. Untuk memeriksa apakahsomething
adaint
ataustr
digunakanisinstance(something, (int, str))
.