Bagaimana cara membandingkan jenis objek dengan Python?

163

Pada dasarnya saya ingin melakukan ini:

obj = 'str'
type ( obj ) == string

Saya mencoba:

type ( obj ) == type ( string )

dan itu tidak berhasil.

Juga, bagaimana dengan tipe lainnya? Misalnya, saya tidak bisa meniru NoneType.

Joan Venge
sumber
Ini berfungsitype(obj) == str
Joshua Varghese

Jawaban:

241
isinstance()

Dalam kasus Anda, isinstance("this is a string", str)akan kembali True.

Anda mungkin juga ingin membaca ini: http://www.canonical.org/~kragen/isinstance/

anthony
sumber
4
Saya akan mengatakan Anda (OP) pasti harus membaca tautan yang direferensikan, yang memberikan banyak detail mengapa memeriksa jenis objek biasanya merupakan ide yang buruk, dan apa yang seharusnya Anda lakukan.
Jeff Shannon
2
Anda harus menggunakan basestr, bukan str. jika tidak, Anda tidak akan memilih unicode. (meskipun untuk 3.x saya pikir str adalah yang basestr)
Hasen
36

isinstance bekerja:

if isinstance(obj, MyClass): do_foo(obj)

tetapi , perlu diingat: jika itu terlihat seperti bebek, dan jika itu terdengar seperti bebek, itu adalah bebek.

Sunting: Untuk jenis Tidak Ada, Anda cukup melakukan:

if obj is None: obj = MyClass()
fengshaun
sumber
def distance_from_zero(n): if isinstance(n,int) or isinstance(n,float): return abs(n) else: return "Nope" print distance_from_zero(True) Ini mengembalikan "1" bukannya "Tidak". Bagaimana menyiasatinya?
dig_123
Jika Anda ingin menggunakan isinstancetetapi periksa juga untuk Nonekemudian isinstance(obj, (MyClass, type(None)))berfungsi. types.NoneTypetelah dihapus dari Python 3 sehingga tidak portabel type(None)untuk mendapatkan referensi NoneType.
Santeri Paavolainen
33

Pertama, hindari semua perbandingan tipe. Mereka sangat, sangat jarang diperlukan. Terkadang, mereka membantu memeriksa tipe parameter dalam suatu fungsi - bahkan itu jarang terjadi. Jenis data yang salah akan menimbulkan pengecualian, dan hanya itu yang Anda perlukan.

Semua fungsi konversi dasar akan dipetakan sama dengan fungsi tipe.

type(9) is int
type(2.5) is float
type('x') is str
type(u'x') is unicode
type(2+3j) is complex

Ada beberapa kasus lain.

isinstance( 'x', basestring )
isinstance( u'u', basestring )
isinstance( 9, int )
isinstance( 2.5, float )
isinstance( (2+3j), complex )

Tidak ada, BTW, tidak pernah membutuhkan jenis pemeriksaan semacam ini. Tidak ada satu-satunya contoh dari NoneType. Objek None adalah Singleton. Cukup periksa Tidak Ada

variable is None

BTW, jangan gunakan di atas secara umum. Gunakan pengecualian biasa dan polimorfisme alami Python sendiri.

S.Lott
sumber
3
Jika Anda memvalidasi input dari DSL, Anda memerlukan semua ini, bahkan NoneType. Bagaimana jika parameter bisa menjadi str, unicodeatau None? isinstance(x, (str, unicode, types.NoneType))jauh lebih bersih daripada memeriksa None. Jika Anda membuat alat untuk perhitungan yang ditunda, atau jika Anda akan meluncurkan proses yang panjang atau padat sumber daya, penting untuk menangkap typekesalahan sebelumnya, selama beberapa langkah validasi khusus. Ini telah menjadi bagian penting dari hampir setiap proyek komputasi ilmiah yang pernah saya kerjakan. Dari semua proyek dev yang saya lihat, lebih banyak membutuhkan ini daripada tidak.
ely
23

Untuk jenis lain, lihat modul jenis :

>>> import types
>>> x = "mystring"
>>> isinstance(x, types.StringType)
True
>>> x = 5
>>> isinstance(x, types.IntType)
True
>>> x = None
>>> isinstance(x, types.NoneType)
True

PS Typechecking adalah ide yang buruk.

Paolo Bergantino
sumber
15

Anda selalu dapat menggunakan type(x) == type(y)triknya, di mana yada sesuatu dengan tipe yang dikenal.

# check if x is a regular string
type(x) == type('')
# check if x is an integer
type(x) == type(1)
# check if x is a NoneType
type(x) == type(None)

Seringkali ada cara yang lebih baik untuk melakukan itu, terutama dengan python baru-baru ini. Tetapi jika Anda hanya ingin mengingat satu hal, Anda dapat mengingatnya.

Dalam hal ini, cara yang lebih baik adalah:

# check if x is a regular string
type(x) == str
# check if x is either a regular string or a unicode string
type(x) in [str, unicode]
# alternatively:
isinstance(x, basestring)
# check if x is an integer
type(x) == int
# check if x is a NoneType
x is None

Perhatikan kasus terakhir: hanya ada satu instance NoneTypedi python, dan itu adalah None. Anda akan melihat NoneType banyak dalam pengecualian ( TypeError: 'NoneType' object is unsubscriptable- terjadi pada saya sepanjang waktu ..) tetapi Anda hampir tidak pernah perlu merujuknya dalam kode.

Akhirnya, seperti yang ditunjukkan fengshaun, mengetik memeriksa python tidak selalu merupakan ide yang baik. Lebih pythonic untuk hanya menggunakan nilai seolah-olah itu adalah tipe yang Anda harapkan, dan menangkap (atau memungkinkan untuk diperbanyak) pengecualian yang dihasilkan dari itu.

John Fouhy
sumber
1
Untuk apa nilainya, isinstance () adalah cara yang disukai untuk memeriksa jenis dalam Python (ketika Anda harus melakukannya).
David Z
6

Anda sangat dekat! stringadalah modul, bukan tipe. Anda mungkin ingin membandingkan jenis objterhadap objek tipe untuk string, yaitu str:

type(obj) == str  # this works because str is already a type

Kalau tidak:

type(obj) == type('')

Catatan, dalam Python 2, jika objmerupakan tipe unicode, maka tak satu pun dari yang di atas akan berfungsi. Tidak akan isinstance(). Lihat komentar John pada postingan ini untuk mengetahui bagaimana caranya ... Saya sudah mencoba mengingatnya sekitar 10 menit sekarang, tetapi mengalami blok memori!

Jarret Hardie
sumber
2
Gunakan basestring dengan isinstance () untuk mendapatkan str dan unicode.
John Fouhy
5

Itu karena Anda harus menulis

s="hello"
type(s) == type("")

ketik menerima sebuah instance dan mengembalikan tipenya. Dalam hal ini Anda harus membandingkan dua tipe instance.

Jika Anda perlu melakukan pemeriksaan preemptive, lebih baik jika Anda memeriksa antarmuka yang didukung daripada jenisnya.

Tipe ini tidak terlalu banyak memberi tahu Anda, terlepas dari kenyataan bahwa kode Anda menginginkan instance dari tipe tertentu, terlepas dari fakta bahwa Anda dapat memiliki instance lain dari tipe yang sama sekali berbeda yang akan sangat baik karena mengimplementasikan antarmuka yang sama .

Misalnya, anggap Anda memiliki kode ini

def firstElement(parameter):
    return parameter[0]

Sekarang, anggaplah Anda berkata: Saya ingin kode ini hanya menerima tuple.

import types

def firstElement(parameter):
    if type(parameter) != types.TupleType:
         raise TypeError("function accepts only a tuple")
    return parameter[0]

Ini mengurangi penggunaan kembali rutin ini. Ini tidak akan berfungsi jika Anda melewati daftar, atau string, atau numpy.array. Sesuatu yang lebih baik

def firstElement(parameter):
    if not (hasattr(parameter, "__getitem__") and callable(getattr(parameter,"__getitem__"))):
        raise TypeError("interface violation")
    return parameter[0]

tetapi tidak ada gunanya melakukannya: parameter [0] akan memunculkan pengecualian jika protokolnya tidak terpenuhi ... ini tentu saja kecuali Anda ingin mencegah efek samping atau harus memulihkan dari panggilan yang dapat Anda panggil sebelum gagal. Contoh (bodoh), hanya untuk menjelaskan:

def firstElement(parameter):
    if not (hasattr(parameter, "__getitem__") and callable(getattr(parameter,"__getitem__"))):
        raise TypeError("interface violation")
    os.system("rm file")
    return parameter[0]

dalam hal ini, kode Anda akan menimbulkan pengecualian sebelum menjalankan panggilan sistem (). Tanpa pemeriksaan antarmuka, Anda akan menghapus file tersebut, dan kemudian mengangkat pengecualian.

Stefano Borini
sumber
Terima kasih telah menunjukkan cara yang lebih disukai yang sebenarnya untuk memeriksa antarmuka. Banyak jawaban di sini yang menyebutkannya, tetapi hanya sedikit yang memberikan contoh tentang apa yang baik. Itu masih tidak menjawab pertanyaan pribadi saya secara langsung (saya mencoba untuk memisahkan daftar string, berisi banyak item yang bermakna, dari string, yang berisi banyak item, bukan item yang bermakna. Terima kasih!
Nick
5

Gunakan str sebagai ganti string

type ( obj ) == str

Penjelasan

>>> a = "Hello"
>>> type(a)==str
True
>>> type(a)
<type 'str'>
>>>
Neil
sumber
4

saya menggunakan type(x) == type(y)

Misalnya, jika saya ingin memeriksa sesuatu adalah array:

type( x ) == type( [] )

periksa string:

type( x ) == type( '' ) or type( x ) == type( u'' )

Jika Anda ingin memeriksa Tidak ada, gunakan adalah

x is None
Hasen
sumber
Hah? mengapa itu ide yang buruk secara umum? Ini hanya ide yang buruk untuk string (untuk pra 3.0) karena ada dua jenis string, str dan unicode. Untuk array, itu ide bagus.
hasen
@ Hasen: ini adalah ide buruk secara keseluruhan. Bagaimana jika saya mendefinisikan tipe saya sendiri yang berperilaku seperti array tetapi, katakanlah, mengambil nilai dari database? Kode Anda akan gagal dengan tipeku tanpa alasan.
nosklo
@hasen: baca tautan canonical.org/~kragen/isinstance jawaban yang paling banyak dipilih (+7), oleh voltronw
nosklo
1
Nah, seluruh alasan (bagi saya setidaknya) dalam memeriksa tipe persis karena saya ingin berurusan dengan array berbeda dari tipe lain (termasuk tipe yang meniru array).
Hasen
2
Anda salah. Saya akan memberikan Anda contoh konkret: Django memiliki shortcut rendering template yang dapat menerima string atau array string. Sekarang, baik string dan array (daftar) dapat diubah, tetapi dalam kasus ini, fungsi-fungsi perlu dibedakan di antara mereka.
Hasen
2

Saya pikir ini harus dilakukan

if isinstance(obj, str)
Aziz
sumber
2

Ketik tidak berfungsi pada kelas-kelas tertentu. Jika Anda tidak yakin dengan jenis objek gunakan __class__metode, seperti:

>>>obj = 'a string'
>>>obj.__class__ == str
True

Lihat juga artikel ini - http://www.siafoo.net/article/56

Toby Fernsler
sumber
2

Untuk mendapatkan tipe, gunakan __class__anggota, seperti padaunknown_thing.__class__

Bicara tentang mengetik bebek tidak berguna di sini karena tidak menjawab pertanyaan yang sangat bagus. Dalam kode aplikasi saya, saya tidak pernah perlu mengetahui jenis sesuatu, tetapi masih bermanfaat untuk memiliki cara mempelajari jenis objek. Kadang-kadang saya perlu mendapatkan kelas aktual untuk memvalidasi tes unit. Mengetik bebek menghalangi jalan karena semua objek yang mungkin memiliki API yang sama, tetapi hanya satu yang benar. Juga, kadang-kadang saya menjaga kode orang lain, dan saya tidak tahu objek apa yang telah saya lewati. Ini adalah masalah terbesar saya dengan bahasa yang diketik secara dinamis seperti Python. Versi 1 sangat mudah dan cepat untuk dikembangkan. Versi 2 sangat menyusahkan roti, terutama jika Anda tidak menulis versi 1. Jadi, kadang-kadang, ketika saya bekerja dengan fungsi yang tidak saya tulis, saya perlu tahu jenis parameternya,

Di situlah __class__parameter berguna. Itu (sejauh yang saya tahu) adalah cara terbaik (mungkin satu-satunya cara) untuk mendapatkan jenis objek.

MiguelMunoz
sumber
2

Gunakan isinstance(object, type). Seperti di atas ini mudah digunakan jika Anda tahu yang benar type, misalnya,

isinstance('dog', str) ## gives bool True

Tetapi untuk objek yang lebih esoteris, ini bisa sulit digunakan. Sebagai contoh:

import numpy as np 
a = np.array([1,2,3]) 
isinstance(a,np.array) ## breaks

tetapi Anda dapat melakukan trik ini:

y = type(np.array([1]))
isinstance(a,y) ## gives bool True 

Jadi saya sarankan instantiating variabel ( ydalam hal ini) dengan jenis objek yang ingin Anda periksa (misalnya, type(np.array())), kemudian gunakan isinstance.

travelingbones
sumber
0

Anda dapat membandingkan kelas untuk level pemeriksaan.

#!/usr/bin/env python
#coding:utf8

class A(object):
    def t(self):
        print 'A'
    def r(self):
        print 'rA',
        self.t()

class B(A):
    def t(self):
        print 'B'

class C(A):
    def t(self):
        print 'C'

class D(B, C):
    def t(self):
        print 'D',
        super(D, self).t()

class E(C, B):
    pass

d = D()
d.t()
d.r()

e = E()
e.t()
e.r()

print isinstance(e, D) # False
print isinstance(e, E) # True
print isinstance(e, C) # True
print isinstance(e, B) # True
print isinstance(e, (A,)) # True
print e.__class__ >= A, #False
print e.__class__ <= C, #False
print e.__class__ <  E, #False
print e.__class__ <= E  #True
mempercepat
sumber