Apakah ada cara sederhana untuk menentukan apakah suatu variabel adalah daftar, kamus, atau sesuatu yang lain? Saya mendapatkan objek kembali yang mungkin tipe baik dan saya harus bisa membedakannya.
python
dictionary
types
typeof
Justin Ethier
sumber
sumber
try
tidak membantu. Misalnya, jika Anda tahu bahwa pengguna dapat meneruskan string atau array, keduanya dapat indeks, tetapi indeks itu berarti sesuatu yang sama sekali berbeda. Cukup mengandalkan try-catch dalam kasus-kasus itu akan gagal dengan cara yang tidak terduga dan aneh. Salah satu solusinya adalah dengan membuat metode terpisah, yang lain untuk menambahkan pengecekan tipe kecil. Saya pribadi lebih suka perilaku polimorfik daripada beberapa metode yang melakukan hal yang hampir sama ... tapi itu hanya saya :)Jawaban:
Ada dua fungsi bawaan yang membantu Anda mengidentifikasi jenis objek. Anda dapat menggunakan
type()
jika Anda membutuhkan jenis objek yang tepat, danisinstance()
untuk memeriksa jenis objek terhadap sesuatu. Biasanya, Anda ingin menggunakanisistance()
sebagian besar waktu karena sangat kuat dan juga mendukung tipe warisan.Untuk mendapatkan jenis objek yang sebenarnya, Anda menggunakan
type()
fungsi bawaan. Melewati objek sebagai satu-satunya parameter akan mengembalikan objek tipe objek itu:Ini tentu saja juga berfungsi untuk jenis khusus:
Perhatikan bahwa
type()
hanya akan mengembalikan tipe objek langsung, tetapi tidak akan dapat memberi tahu Anda tentang jenis pewarisan.Untuk mengatasinya, Anda harus menggunakan
isinstance
fungsi ini. Ini tentu saja juga berfungsi untuk tipe bawaan:isinstance()
biasanya merupakan cara yang lebih disukai untuk memastikan jenis objek karena ia juga akan menerima jenis turunan. Jadi kecuali Anda benar-benar membutuhkan objek jenis (untuk alasan apa pun), menggunakanisinstance()
lebih disukaitype()
.Parameter kedua
isinstance()
juga menerima tupel jenis, jadi dimungkinkan untuk memeriksa beberapa jenis sekaligus.isinstance
kemudian akan mengembalikan true, jika objeknya adalah salah satu dari jenis tersebut:sumber
is
daripada==
jenisnya adalah lajangisinstance
sejak awal), adalah bentuk yang disukai, jadi tidak perlu==
atau tidakis
perlu digunakan.type
adalah jawaban terbaik. Ada kalanyaisinstance
adalah jawaban terbaik dan ada kalanya mengetik bebek adalah jawaban terbaik. Sangat penting untuk mengetahui semua opsi sehingga Anda dapat memilih mana yang lebih tepat untuk situasi tersebut.type(foo) is SomeType
akan lebih baik daripadaisinstance(foo, SomeType)
.isinstance
untuk usecase Anda (memeriksa berbagai jenis) juga, dan dengan membersihkan sintaks juga, yang memiliki keuntungan besar yang dapat Anda ambil subclass. seseorang yang menggunakanOrderedDict
akan membenci kode Anda gagal karena hanya menerima dicts murni.Anda dapat melakukannya menggunakan
type()
:sumber
Mungkin lebih Pythonic untuk menggunakan
try
...except
blok. Dengan begitu, jika Anda memiliki kelas yang dukun seperti daftar, atau dukun seperti dict, itu akan berperilaku baik terlepas dari apa tipenya sebenarnya .Untuk memperjelas, metode yang disukai "mengatakan perbedaan" antara tipe variabel adalah dengan sesuatu yang disebut bebek mengetik : selama metode (dan tipe pengembalian) yang ditanggapi oleh variabel adalah apa yang diharapkan oleh subrutin Anda, perlakukan seperti apa yang Anda harapkan menjadi. Misalnya, jika Anda memiliki kelas yang membebani operator braket dengan
getattr
dansetattr
, tetapi menggunakan beberapa skema internal yang lucu, itu akan sesuai untuk itu berperilaku sebagai kamus jika itu yang ingin ditiru.Masalah lain dengan
type(A) is type(B)
pemeriksaan adalah bahwa jikaA
merupakan subkelas dariB
, itu mengevaluasifalse
kapan, secara pemrograman, Anda akan berharap itu akan terjaditrue
. Jika suatu objek adalah subclass dari daftar, itu harus berfungsi seperti daftar: memeriksa jenis seperti yang disajikan dalam jawaban lain akan mencegah hal ini. (isinstance
akan bekerja, namun).sumber
try
...except
adalah solusi yang baik ketika Anda ingin menangani kesalahan, tetapi tidak saat memutuskan perilaku berdasarkan tipe.Pada contoh objek Anda juga memiliki:
atribut. Berikut adalah contoh yang diambil dari konsol Python 3.3
Berhati-hatilah bahwa dalam python 3.x dan di kelas New-Style (dapat dipilih secara opsional dari Python 2.6) kelas dan tipe telah digabungkan dan ini kadang-kadang dapat menyebabkan hasil yang tidak terduga. Terutama karena alasan ini cara favorit saya untuk menguji jenis / kelas adalah dengan isinstance built in function.
sumber
__class__
sebagian besar OK pada Python 2.x, satu-satunya objek di Python yang tidak memiliki__class__
atribut adalah kelas gaya lama AFAIK. Ngomong-ngomong, saya tidak mengerti masalah Python 3 Anda - pada versi seperti itu, hanya setiap objek memiliki__class__
atribut yang menunjuk ke kelas yang tepat.Tentukan jenis objek Python
Tentukan jenis objek dengan
type
Meskipun berfungsi, hindari atribut bergaris bawah ganda seperti
__class__
- mereka tidak bersifat publik semantik, dan, meskipun mungkin tidak dalam kasus ini, fungsi bawaan biasanya memiliki perilaku yang lebih baik.memeriksa jenis
Nah itu pertanyaan yang berbeda, jangan gunakan tipe - gunakan
isinstance
:Ini mencakup kasus di mana pengguna Anda mungkin melakukan sesuatu yang pintar atau masuk akal dengan subkelas
str
- sesuai dengan prinsip Pergantian Liskov, Anda ingin dapat menggunakan contoh subkelas tanpa melanggar kode Anda - danisinstance
mendukung ini.Gunakan Abstraksi
Bahkan lebih baik, Anda mungkin mencari Kelas Dasar Abstrak spesifik dari
collections
ataunumbers
:Atau Hanya Jangan Ketikkan-centang secara eksplisit
Atau, mungkin yang terbaik, gunakan bebek-mengetik, dan jangan ketik-periksa kode Anda secara eksplisit. Mengetik bebek mendukung Substitusi Liskov dengan keanggunan yang lebih tinggi dan lebih sedikit.
Kesimpulan
type
untuk benar-benar mendapatkan kelas instance.isinstance
untuk secara eksplisit memeriksa subclass aktual atau abstraksi terdaftar.sumber
try
/except
bukannya memeriksa secara eksplisit.Anda bisa menggunakan
type()
atauisinstance()
.Berhati-hatilah bahwa Anda dapat mengalahkan
list
atau tipe lain dengan menetapkan variabel dalam lingkup nama yang sama saat ini.Di atas kita melihat bahwa
dict
akan dipindahkan ke string, oleh karena itu tes:... gagal.
Untuk menyiasati ini dan menggunakan
type()
lebih hati-hati:sumber
dict
String Anda juga akan gagal untuk banyak kode lain, sepertidict([("key1", "value1"), ("key2", "value2")])
. Jawaban untuk masalah-masalah semacam itu adalah "Kalau begitu jangan lakukan itu" . Jangan membayangi nama tipe bawaan dan mengharapkan sesuatu berfungsi dengan baik.Meskipun pertanyaannya sudah cukup lama, saya menemukan ini sambil menemukan sendiri cara yang tepat, dan saya pikir itu masih perlu diklarifikasi, setidaknya untuk Python 2.x (tidak memeriksa Python 3, tetapi karena masalah muncul dengan kelas klasik yang hilang pada versi seperti itu, mungkin tidak masalah).
Di sini saya mencoba menjawab pertanyaan judul: bagaimana saya bisa menentukan jenis objek yang berubah-ubah ? Saran lain tentang menggunakan atau tidak menggunakan isinstance baik-baik saja di banyak komentar dan jawaban, tapi saya tidak membahas masalah itu.
Masalah utama dengan
type()
pendekatan ini adalah bahwa itu tidak berfungsi dengan baik dengan contoh gaya lama :Menjalankan potongan ini akan menghasilkan:
Yang, menurut saya, bukan yang diharapkan kebanyakan orang.
The
__class__
pendekatan adalah yang paling dekat dengan kebenaran, tetapi itu tidak akan bekerja dalam satu kasus penting: ketika lulus-in objek adalah gaya lama kelas (! Bukan sebuah contoh), karena benda-benda kekurangan atribut tersebut.Ini adalah cuplikan kode terkecil yang dapat saya pikirkan yang memenuhi pertanyaan sah seperti itu secara konsisten:
sumber
hati-hati menggunakan isinstance
tapi ketik
sumber
Selain jawaban sebelumnya, ada baiknya menyebutkan keberadaan
collections.abc
yang berisi beberapa kelas dasar abstrak (ABC) yang melengkapi mengetik bebek.Misalnya, alih-alih secara eksplisit memeriksa apakah ada daftar dengan:
Anda bisa, jika Anda hanya tertarik untuk melihat apakah objek yang Anda miliki memungkinkan mendapatkan barang, gunakan
collections.abc.Sequence
:jika Anda benar-benar tertarik pada objek yang memungkinkan untuk mendapatkan, mengatur, dan menghapus item (yaitu urutan yang dapat diubah ), Anda akan memilih
collections.abc.MutableSequence
.Banyak ABC lainnya didefinisikan di sana,
Mapping
untuk objek yang dapat digunakan sebagai peta,Iterable
,Callable
, dan sebagainya. Daftar lengkap semua ini dapat dilihat pada dokumentasi untukcollections.abc
.sumber
Secara umum Anda dapat mengekstraksi string dari objek dengan nama kelas,
dan menggunakannya untuk perbandingan,
sumber
Dalam banyak kasus praktis alih-alih menggunakan
type
atauisinstance
Anda juga dapat menggunakan@functools.singledispatch
, yang digunakan untuk mendefinisikan fungsi generik ( fungsi yang terdiri dari beberapa fungsi yang menerapkan operasi yang sama untuk jenis yang berbeda ).Dengan kata lain, Anda ingin menggunakannya ketika Anda memiliki kode seperti berikut:
Berikut ini adalah contoh kecil cara kerjanya:
Selain itu, kita dapat menggunakan kelas abstrak untuk mencakup beberapa jenis sekaligus:
sumber
type()
adalah solusi yang lebih baik daripadaisinstance()
, terutama untukbooleans
: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