Apa cara terbaik untuk memeriksa apakah suatu objek dari jenis tertentu? Bagaimana memeriksa apakah objek mewarisi dari jenis tertentu?
Let's mengatakan saya memiliki objek o
. Bagaimana cara memeriksa apakah itu's str
?
Untuk memeriksa apakah o
adalah sebuah contoh dari str
atau subclass dari str
, gunakan isinstance (ini akan menjadi "kanonik" cara):
if isinstance(o, str):
Untuk memeriksa apakah jenis o
persis str
(mengecualikan subclass):
if type(o) is str:
Berikut juga bekerja, dan dapat berguna dalam beberapa kasus:
if issubclass(type(o), str):
Lihat Fungsi Built-in dalam Python Referensi Perpustakaan untuk informasi yang relevan.
Satu lagi catatan: dalam hal ini, jika anda're menggunakan python 2, anda mungkin benar-benar ingin menggunakan:
if isinstance(o, basestring):
karena ini juga akan menangkap Unicode string (unicode
adalah sebuah subclass dari str
; kedua str
dan unicode
adalah subclass dari basestring
). Perhatikan bahwa basestring
tidak ada lagi di python 3, di mana di sana's pemisahan yang tegas string (str
) dan data biner (byte
).
Atau, isinstance
menerima sebuah tuple dari kelas. Ini akan mengembalikan True jika x adalah sebuah instance dari subclass dari setiap (str, unicode):
if isinstance(o, (str, unicode)):
The paling Pythonic cara untuk memeriksa jenis sebuah benda adalah... untuk tidak memeriksa itu.
Sejak Python mendorong Duck Typing, anda hanya harus mencoba...kecualiuntuk menggunakan objek's metode cara anda ingin menggunakannya. Jadi jika anda fungsi ini mencari ditulisi file objek, *don't* memeriksa bahwa itu's sebuah subclass dari
file, hanya mencoba untuk menggunakan nya
.write()` metode!
Tentu saja, kadang-kadang ini bagus abstraksi memecah dan isinstance(obj, cls)
adalah apa yang anda butuhkan. Tapi gunakan dengan hemat.
isinstance(o, str)
akan mengembalikan True
jika ya
adalah sebuah str
atau lebih dari jenis yang mewarisi dari str
.
jenis(o) adalah str
akan mengembalikan True
jika dan hanya jika ya
adalah str. Itu akan kembali Palsu
jika ya
adalah dari jenis yang mewarisi dari str
.
Setelah pertanyaan diajukan dan dijawab, jenis petunjuk yang ditambahkan ke Python. Jenis petunjuk di Python memungkinkan untuk diperiksa, tapi dalam cara yang sangat berbeda dari statis diketik bahasa. Jenis petunjuk di Python mengasosiasikan diharapkan jenis argumen dengan fungsi sebagai runtime data yang dapat diakses terkait dengan fungsi dan ini memungkinkan untuk jenis yang akan diperiksa. Contoh dari jenis petunjuk sintaks:
def foo(i: int):
return i
foo(5)
foo('oops')
Dalam hal ini kami ingin sebuah kesalahan yang harus dipicu untuk foo('oops')
sejak dijelaskan jenis argumen int
. Ditambahkan jenis petunjuk tidak penyebab kesalahan terjadi ketika script dijalankan secara normal. Namun, ia menambahkan atribut untuk fungsi yang menggambarkan diharapkan jenis bahwa program-program lain yang dapat query dan menggunakan untuk memeriksa jenis kesalahan.
Salah satu program lain yang dapat digunakan untuk menemukan jenis kesalahan mypy
:
mypy script.py
script.py:12: error: Argument 1 to "foo" has incompatible type "str"; expected "int"
(Anda mungkin perlu menginstal mypy
dari manajer paket anda. Saya don't pikir itu datang dengan CPython tapi tampaknya memiliki beberapa tingkat "officialness".)
Jenis pemeriksaan cara ini berbeda dari tipe check-in statis diketik dihimpun bahasa. Karena jenis yang dinamis dalam Python, jenis pemeriksaan yang harus dilakukan pada saat runtime, yang membebankan biaya-bahkan pada memperbaiki program-jika kita bersikeras bahwa hal itu terjadi di setiap kesempatan. Jenis eksplisit cek juga mungkin lebih ketat daripada yang diperlukan dan menyebabkan kesalahan yang tidak perlu (misalnya apakah argumen yang benar-benar perlu untuk menjadi benar-benar daftar
jenis atau sesuatu yang iterable cukup?).
Terbalik eksplisit jenis pemeriksaan yang dapat menangkap kesalahan sebelumnya dan memberikan lebih jelas pesan kesalahan dari bebek mengetik. Persyaratan yang tepat dari bebek jenis ini hanya dapat diungkapkan dengan eksternal dokumentasi (mudah-mudahan itu's menyeluruh dan akurat) dan kesalahan dari tipe tidak kompatibel dapat terjadi jauh dari mana mereka berasal.
Python's jenis petunjuk yang dimaksudkan untuk menawarkan kompromi di mana jenis dapat ditentukan dan diperiksa tetapi tidak ada biaya tambahan selama eksekusi kode.
The mengetik
menawarkan paket jenis variabel yang dapat digunakan dalam jenis petunjuk untuk mengekspresikan diperlukan perilaku tanpa memerlukan jenis tertentu. Misalnya, mencakup variabel-variabel seperti Iterable
dan Callable
untuk petunjuk untuk menentukan kebutuhan untuk setiap jenis dengan perilaku tersebut.
Sementara jenis petunjuk yang paling Pythonic cara untuk memeriksa jenis, it's bahkan sering lebih Pythonic untuk tidak memeriksa jenis dan mengandalkan bebek mengetik. Jenis petunjuk yang relatif baru dan juri masih keluar pada saat mereka're yang paling Pythonic solusi. Relatif tidak kontroversial, tetapi sangat umum perbandingan: Jenis petunjuk yang memberikan suatu bentuk dokumentasi yang dapat dipaksakan, memungkinkan kode untuk menghasilkan lebih awal dan lebih mudah untuk memahami kesalahan, dapat menangkap kesalahan yang bebek dapat mengetik't, dan dapat diperiksa statis (di sebuah rasa yang tidak biasa tapi itu's masih di luar runtime). Di sisi lain, duck typing telah Pythonic cara untuk waktu yang lama, doesn't memaksakan kognitif overhead statis mengetik, kurang panjang, dan akan layak menerima semua jenis dan beberapa kemudian.
Berikut ini adalah contoh mengapa bebek mengetik adalah kejahatan tanpa mengetahui ketika itu berbahaya. Sebagai contoh: Berikut adalah kode Python (mungkin menghilangkan tepat indentasi), perhatikan bahwa ini situasi ini dapat dihindari dengan merawat isinstance dan issubclassof fungsi untuk memastikan bahwa ketika anda benar-benar membutuhkan bebek, anda don't mendapatkan sebuah bom.
class Bomb:
def __init__(self):
""
def talk(self):
self.explode()
def explode(self):
print "BOOM!, The bomb explodes."
class Duck:
def __init__(self):
""
def talk(self):
print "I am a duck, I will not blow up if you ask me to talk."
class Kid:
kids_duck = None
def __init__(self):
print "Kid comes around a corner and asks you for money so he could buy a duck."
def takeDuck(self, duck):
self.kids_duck = duck
print "The kid accepts the duck, and happily skips along"
def doYourThing(self):
print "The kid tries to get the duck to talk"
self.kids_duck.talk()
myKid = Kid()
myBomb = Bomb()
myKid.takeDuck(myBomb)
myKid.doYourThing()
isinstance(o, str)
Saya pikir hal yang keren tentang menggunakan bahasa dinamis seperti Python adalah anda benar-benar tidak't harus memeriksa sesuatu seperti itu.
Saya hanya akan memanggil diperlukan metode pada objek dan menangkap AttributeError
. Nanti ini akan memungkinkan anda untuk memanggil anda dengan metode lain (yang tampaknya tidak berhubungan) benda-benda untuk menyelesaikan tugas-tugas yang berbeda, seperti mengejek objek untuk pengujian.
I've digunakan ini banyak ketika mendapatkan data dari web dengan urllib2.urlopen()
yang kembali file like objek. Hal ini pada gilirannya dapat diteruskan ke hampir semua metode yang membaca dari sebuah file, karena menerapkan hal yang sama read()
metode sebagai file nyata.
Tapi aku'm yakin ada waktu dan tempat untuk menggunakan isinstance()
, jika tidak maka mungkin tidak't berada di sana :)
Hugo:
Anda mungkin berarti daftar
daripada array
, tapi yang poin untuk seluruh masalah dengan jenis pemeriksaan - anda don't ingin tahu apakah objek tersebut adalah sebuah daftar, anda ingin tahu apakah itu's beberapa jenis urutan atau jika itu's sebuah objek tunggal. Jadi cobalah untuk menggunakannya seperti urutan.
Katakanlah anda ingin menambahkan objek dengan urutan yang ada, atau jika itu's urutan objek, tambahkan mereka semua
try:
my_sequence.extend(o)
except TypeError:
my_sequence.append(o)
Salah satu trik dengan hal ini adalah jika anda bekerja dengan string dan/atau urutan string - yang's rumit, karena string adalah sering dianggap sebagai objek tunggal, tetapi itu's juga urutan karakter. Lebih buruk dari itu, sebagai it's benar-benar urutan tunggal-panjang string.
Saya biasanya memilih untuk desain saya API sehingga hanya menerima salah satu nilai atau urutan - itu membuat segalanya lebih mudah. It's tidak sulit untuk menempatkan [ ]
di sekitar anda nilai tunggal ketika anda lulus dalam jika perlu.
(Meskipun hal ini dapat menyebabkan kesalahan dengan string, seperti yang mereka lakukan terlihat seperti (yang) urutan.)
Untuk yang lebih kompleks jenis validasi yang saya suka typeguard's pendekatan validasi berdasarkan jenis python sedikit penjelasan:
from typeguard import check_type
from typing import List
try:
check_type('mylist', [1, 2], List[int])
except TypeError as e:
print(e)
Anda dapat melakukan sangat kompleks validasi dalam sangat bersih dan mudah dibaca fashion.
check_type('foo', [1, 3.14], List[Union[int, float]])
# vs
isinstance(foo, list) and all(isinstance(a, (int, float)) for a in foo)
Anda dapat memeriksa dengan di bawah garis untuk memeriksa karakter yang jenis nilai yang diberikan adalah:
def chr_type(chrx):
if chrx.isalpha()==True:
return 'alpha'
elif chrx.isdigit()==True:
return 'numeric'
else:
return 'nothing'
chr_type("12)