Apa perbedaan antara kedua fragmen kode ini?
Menggunakan type()
:
import types
if type(a) is types.DictType:
do_something()
if type(b) in types.StringTypes:
do_something_else()
Menggunakan isinstance()
:
if isinstance(a, dict):
do_something()
if isinstance(b, str) or isinstance(b, unicode):
do_something_else()
python
oop
inheritance
types
kepala biara
sumber
sumber
str
danunicode
(tempat Anda dapat memeriksabasestring
), Anda dapat menggunakan tuple untuk memeriksa beberapa tipe. Untuk memeriksa apakahsomething
adaint
ataustr
digunakanisinstance(something, (int, str))
.Jawaban:
Untuk meringkas isi dari jawaban lain (sudah bagus!),
isinstance
Melayani warisan (turunan dari kelas turunan juga merupakan turunan dari kelas dasar), sambil memeriksa persamaantype
tidak (menuntut identitas tipe dan menolak instance) subtipe, subclass AKA).Biasanya, dengan Python, Anda ingin kode Anda mendukung warisan, tentu saja (karena warisan sangat berguna, akan sangat buruk untuk menghentikan kode menggunakan Anda dari menggunakannya!), Jadi
isinstance
lebih buruk daripada memeriksa identitastype
s karena mendukung mulus warisan.Ini bukan berarti bahwa
isinstance
adalah baik , pikiran Anda-itu hanya kurang buruk daripada memeriksa kesetaraan jenis. Solusi normal, Pythonic, yang disukai hampir selalu "mengetik bebek": coba gunakan argumen seolah-olah itu dari jenis yang diinginkan, lakukan dalamtry
/except
pernyataan menangkap semua pengecualian yang dapat muncul jika argumen itu tidak sebenarnya ketik (atau jenis lain dengan baik meniru-nya ;-), dan dalamexcept
klausa, coba sesuatu yang lain (menggunakan argumen "seolah-olah" itu dari jenis lain).basestring
adalah , bagaimanapun, cukup kasus-tipe builtin khusus yang ada hanya untuk membiarkan Anda menggunakanisinstance
(baikstr
danunicode
subclassbasestring
). String adalah urutan (Anda dapat mengulanginya, mengindeksnya, mengirisnya, ...), tetapi Anda umumnya ingin memperlakukannya sebagai tipe "skalar" —rasanya agak tidak menentu (tetapi kasus penggunaan yang cukup sering) untuk menangani semua jenis string (dan mungkin jenis skalar lainnya, yaitu yang tidak dapat Anda lewati) dengan satu cara, semua wadah (daftar, set, dicts, ...) dengan cara lain, danbasestring
plusisinstance
membantu Anda melakukan itu — struktur keseluruhan dari ini idiom adalah sesuatu seperti:Anda bisa mengatakan bahwa itu
basestring
adalah Kelas Dasar Abstrak ("ABC") - ia tidak menawarkan fungsionalitas konkret untuk subkelas, melainkan ada sebagai "penanda", terutama untuk digunakan bersamaisinstance
. Konsep ini jelas berkembang di Python, karena PEP 3119 , yang memperkenalkan generalisasi, diterima dan telah diterapkan mulai dengan Python 2.6 dan 3.0.PEP memperjelas bahwa, meskipun ABC sering dapat menggantikan mengetik bebek, umumnya tidak ada tekanan besar untuk melakukan itu (lihat di sini ). Namun, ABC yang diterapkan dalam versi Python terbaru menawarkan barang tambahan:
isinstance
(danissubclass
) sekarang dapat berarti lebih dari sekadar "[turunan dari] kelas turunan" (khususnya, kelas apa pun dapat "didaftarkan" dengan ABC sehingga akan ditampilkan sebagai subkelas, dan instansnya sebagai instance dari ABC); dan ABC juga dapat menawarkan kenyamanan ekstra untuk subclass aktual dengan cara yang sangat alami melalui aplikasi pola desain Metode Templat (lihat di sini dan di sini [[bagian II]] untuk lebih lanjut tentang TM DP, secara umum dan khusus dalam Python, independen dari ABC) .Untuk mekanisme yang mendasari dukungan ABC seperti yang ditawarkan dalam Python 2.6, lihat di sini ; untuk versi 3.1 mereka, sangat mirip, lihat di sini . Di kedua versi, koleksi modul perpustakaan standar (itulah versi 3.1 — untuk versi 2.6 yang sangat mirip, lihat di sini ) menawarkan beberapa ABC yang bermanfaat.
Untuk keperluan jawaban ini, hal utama untuk mempertahankan tentang ABC (di luar penempatan yang lebih alami untuk fungsi TM DP, dibandingkan dengan alternatif klasik Python dari kelas mixin seperti UserDict.DictMixin ) adalah mereka membuat
isinstance
(danissubclass
) lebih banyak menarik dan meresap (dalam Python 2.6 dan melangkah maju) daripada sebelumnya (dalam 2.5 dan sebelumnya), dan oleh karena itu, sebaliknya, menjadikan pemeriksaan kesetaraan jenis praktik yang lebih buruk dalam versi Python terbaru daripada yang sudah pernah ada sebelumnya.sumber
Berikut adalah contoh di mana
isinstance
mencapai sesuatu yangtype
tidak bisa:dalam hal ini, objek truk adalah Kendaraan, tetapi Anda akan mendapatkan ini:
Dengan kata lain,
isinstance
berlaku juga untuk subkelas.Lihat juga: Bagaimana membandingkan jenis objek dengan Python?
sumber
type
sudah usang, gunakanisinstance
sebagai gantinya" pada pandangan pertama. misalnya, apa yang saya inginkan sebenarnya adalahtype()
pengecekan, tetapi saya disesatkan untuk waktu yang singkat (dan harus melakukan debug sedikit) karena alasan itu.type()
dan tidakisinstance()
. Seseorang tidak lebih baik; mereka untuk hal yang berbeda.Ketik memeriksa dengan
memungkinkan untuk instance dari subclass dan beberapa basis yang mungkin:
sedangkan jenis-memeriksa dengan
hanya mendukung jenis yang dirujuk.
Sebagai seorang sidenote,
is
kemungkinan lebih tepat daripadakarena 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.
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:
atau yang berfungsi seperti bebek:
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()
dantype()
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:
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 !:menimbulkan kesalahan!
isinstance
Tetapi jika kita menggunakan
isinstance
, kita dapat mendukung Substitusi Liskov !: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 mengharapkanMapping
protokol, kami dapat melakukan hal berikut, dan kode kami menjadi lebih fleksibel:Tanggapan terhadap komentar:
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:
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 tipeisinstance
- kecuali Anda benar-benar perlu mengetahui kelas yang tepat dari sebuah instance.sumber
isinstance(instance, y)
dan menggunakanfrom v.w.x import y
, dan Anda mengimpor cek itu, tetapi ketika Anda instantiateinstance
Anda menggunakanfrom x import y
alih-alih bagaimana Anda diimpor di your_module.py, pemeriksaan status akan gagal, meskipun itu kelas yang sama.Yang terakhir lebih disukai, karena akan menangani subclass dengan benar. Bahkan, contoh Anda dapat ditulis lebih mudah karena
isinstance()
parameter kedua mungkin tupel:atau, menggunakan
basestring
kelas abstrak:sumber
Menurut dokumentasi python di sini adalah pernyataan:
Jadi
isinstance()
sebaiknya lebih disukaitype()
.sumber
Perbedaan penggunaan praktis adalah bagaimana mereka menangani
booleans
:True
danFalse
hanya kata kunci yang berarti1
dan0
dengan python. Jadi,dan
keduanya kembali
True
. Kedua boolean adalah turunan dari bilangan bulat.type()
Namun, lebih pintar:kembali
False
.sumber
Untuk perbedaan nyata, kita dapat menemukannya di
code
, tetapi saya tidak dapat menemukan penerapan perilaku default dariisinstance()
.Namun kita bisa mendapatkan yang serupa abc .__ instancecheck__ menurut __instancecheck__ .
Dari atas
abc.__instancecheck__
, setelah menggunakan tes di bawah ini:Saya mendapatkan kesimpulan ini, Untuk
type
:Untuk
isinstance
:BTW: lebih baik tidak mencampur penggunaan
relative and absolutely import
, gunakanabsolutely import
dari project_dir (ditambahkan olehsys.path
)sumber