Python'da bir nesnenin türü nasıl karşılaştırılır?


163

Temelde bunu yapmak istiyorum:

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

Denedim:

type ( obj ) == type ( string )

ve işe yaramadı.

Ayrıca, diğer türler ne olacak? Mesela çoğaltamadım NoneType.


Bu esertype(obj) == str
Joshua Varghese

Yanıtlar:


241
isinstance()

Senin durumunda, isinstance("this is a string", str)geri dönecek True.

Bunu da okumak isteyebilirsiniz: http://www.canonical.org/~kragen/isinstance/


4
Size (OP) kesinlikle referans verilen bağlantıyı okumalısınız, bu da bir nesnenin türünü neden kontrol etmenin genellikle kötü bir fikir olduğunu ve bunun yerine muhtemelen ne yapmanız gerektiğini bolca ayrıntı verir.
Jeff Shannon

2
str değil basestr kullanmalısınız. aksi takdirde unicode seçmezsiniz. (3.x için bence rağmen str olan basestr)
Hasen

36

isinstance İşler:

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

ancak unutmayın: ördek gibi görünüyorsa ve ördek gibi geliyorsa, ördek demektir.

EDIT: Hiçbiri türü için şunları yapabilirsiniz:

if obj is None: obj = MyClass()

def distance_from_zero(n): if isinstance(n,int) or isinstance(n,float): return abs(n) else: return "Nope" print distance_from_zero(True) Bu, "Hayır" yerine "1" değerini döndürür. Bu nasıl yapılır?
dig_123

Kullanmak isinstanceama aynı zamanda kontrol etmek istiyorsanız Noneo zaman isinstance(obj, (MyClass, type(None)))çalışır. types.NoneTypePython 3'ten kaldırılmıştır, bu nedenle type(None)referans almak kadar taşınabilir değildir NoneType.
Santeri Paavolainen

33

İlk olarak, tüm tür karşılaştırmalarından kaçının. Çok, çok nadiren gereklidirler. Bazen, bir işlevdeki parametre türlerini kontrol etmeye yardımcı olurlar - bu nadir de olsa. Yanlış tür verileri bir istisna oluşturacak ve ihtiyacınız olan tek şey bu.

Tüm temel dönüştürme işlevleri, type işlevine eşit olarak eşlenir.

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

Birkaç vaka daha var.

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

Hiçbiri, BTW, asla bu tür tip kontrollere ihtiyaç duymaz. Hiçbiri, NoneType'ın tek örneğidir. None nesnesi bir Singleton'dur. Yok'u kontrol edin

variable is None

BTW, genel olarak yukarıdakileri kullanmayın. Sıradan istisnalar ve Python'un kendi doğal polimorfizmini kullanın.


3
Bir DSL'den gelen girişleri doğrulıyorsanız, tüm bunlara ihtiyacınız vardır NoneType. Bir parametre ne bir eğer str, unicodeya None? isinstance(x, (str, unicode, types.NoneType))kontrol etmekten çok daha temiz None. Ertelenmiş hesaplama için araçlar oluşturuyorsanız veya uzun veya yoğun kaynak gerektiren bir işlem başlatmak üzereyseniz type, bazı özel doğrulama adımları sırasında hataları önceden yakalamak önemlidir . Bu, üzerinde çalıştığım hemen hemen her bilimsel bilgi işlem projesinin kritik bir parçası oldu. Gördüğüm tüm dev projelerinden buna gerek duymadıklarından daha fazlasına ihtiyaç var.
ely

23

Diğer türler için türler modülüne göz atın:

>>> 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 kötü bir fikirdir.


15

Bilinen tipte bir şey olan her zaman type(x) == type(y)hileyi kullanabilirsiniz y.

# 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)

Genellikle bunu yapmanın daha iyi yolları vardır, özellikle de yeni bir python ile. Ama sadece bir şeyi hatırlamak istiyorsanız, bunu hatırlayabilirsiniz.

Bu durumda, daha iyi yollar:

# 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

Son durumu not edin: Python'da yalnızca bir örnek var NoneTypeve bu None. İstisnalar dışında NoneType'ı çok fazla göreceksiniz ( TypeError: 'NoneType' object is unsubscriptable- her zaman başıma geliyor ..) ama kodda ona başvurmanız gerekmiyor.

Son olarak, fengshaun'un işaret ettiği gibi, python'da tip kontrolü her zaman iyi bir fikir değildir. Değeri yalnızca beklediğiniz tür gibi kullanmak ve bundan kaynaklanan istisnaları yakalamak (veya yaymaya izin vermek) için daha pitoniktir.


1
Değer için, isinstance (), Python'daki türleri kontrol etmenin tercih edilen yoludur (bunu yapmanız gerektiğinde).
David Z

6

Çok yakınsın! stringbir modüldür, bir tür değildir. Muhtemelen objdizeler için type nesnesinin türünü karşılaştırmak istersiniz , yani str:

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

Alternatif:

type(obj) == type('')

Unutmayın, Python 2'de, objbir unicode türü ise, yukarıdakilerin hiçbiri çalışmaz. Olmayacak isinstance(). Bu sorunun üstesinden gelmek için bu gönderinin yorumlarına bakın ... 10 dakikayı hatırlamaya çalışıyorum ama bir hafıza bloğum vardı!


2
Hem str hem de unicode'u almak için isinstance () ile basestring kullanın.
John Fouhy

5

Çünkü yazmak zorundasın

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

type bir örneği kabul eder ve türünü döndürür. Bu durumda iki örneğin türünü karşılaştırmanız gerekir.

Önleyici kontrol yapmanız gerekiyorsa, desteklenen bir arabirimi kontrol etmek türden daha iyidir.

Tür, aynı arabirimi uyguladığı için mükemmel şekilde iyi olacak tamamen farklı bir türün başka bir örneğine sahip olabileceğinize bakılmaksızın, kodunuzun belirli bir türün bir örneğini istediği gerçeği dışında, size çok fazla şey anlatmaz. .

Örneğin, bu koda sahip olduğunuzu varsayalım

def firstElement(parameter):
    return parameter[0]

Şimdi, diyelim ki bu kodun sadece bir demet kabul etmesini istiyorum.

import types

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

Bu, bu rutinin tekrar kullanılabilirliğini azaltır. Bir liste, dize veya numpy.array iletirseniz çalışmaz. Daha iyi bir şey olurdu

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

ancak bunu yapmanın bir anlamı yoktur: [0] parametresi, protokol yine de tatmin olmazsa bir istisna oluşturur ... tabii ki yan etkileri önlemek veya başarısız olmadan önce çağırabileceğiniz çağrılardan kurtulmak istemiyorsanız. (Aptal) örnek, sadece noktayı belirtmek için:

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

bu durumda, sistem () çağrısını çalıştırmadan önce kodunuz bir istisna oluşturur. Arabirim denetimleri olmadan, dosyayı kaldırır ve ardından özel durumu yükseltirsiniz.


Arayüzleri kontrol etmek için gerçek tercih edilen yolu belirttiğiniz için teşekkür ederiz. Buradaki cevapların çoğu bundan bahsediyor, ancak çok azı bunun yerine neyin iyi olduğuna dair örnekler veriyor. Yine de kişisel soruma doğrudan cevap vermiyor (birçok anlamlı öğe içeren dizelerin listesini, anlamlı olmayan pek çok öğe içeren bir dizeden ayırmaya çalışıyorum. Teşekkürler!
Nick

5

Dize yerine str kullan

type ( obj ) == str

açıklama

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

4

kullanırım type(x) == type(y)

Örneğin, bir şey bir dizi olduğunu kontrol etmek istiyorsanız:

type( x ) == type( [] )

dize denetimi:

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

Yok'a karşı kontrol etmek istiyorsanız,

x is None

ha? neden genel olarak kötü bir fikir? Dizeler için kötü bir fikir (3.0 öncesi için) çünkü str ve unicode olmak üzere iki tür dizgi vardır. Diziler için iyi bir fikir imho.
hasen

@hasen: genel olarak kötü bir fikir. Bir dizi gibi davranan, ancak örneğin bir veritabanından değerleri alan kendi türümü tanımlarsam ne olur? Kodunuz hiçbir nedenle türümde başarısız olacak.
nosklo

@hasen: voltronw tarafından yapılan canonical.org/~kragen/isinstance cevabını okuyun (+7), yazan voltronw
nosklo

1
Türü kontrol etmemdeki tüm neden (en azından benim için), dizileri diğer türlerden (dizileri taklit eden türler dahil) farklı şekilde ele almak istediğimden kaynaklanmaktadır.
hasen

2
Yanılıyorsun. Size somut bir örnek vereceğim: django, bir dizeyi veya dizeleri kabul edebilecek bir şablon oluşturma kısayoluna sahiptir. Şimdi, hem dizeler hem de diziler (listeler) yinelenebilir, ancak bu durumda, işlevlerin aralarında ayrım yapması gerekir.
hasen

2

bence bunu yapmalı

if isinstance(obj, str)


2

Türü almak için __class__üyeyi aşağıdaki gibi kullanın :unknown_thing.__class__

Ördek yazmanın konuşması burada işe yaramaz çünkü mükemmel bir soruya cevap vermiyor. Uygulama kodumda asla bir şeyin türünü bilmeme gerek yok, ama yine de bir nesnenin türünü öğrenmenin bir yolu var. Bazen bir birim testi doğrulamak için gerçek sınıfı almak gerekir. Tüm olası nesneler aynı API'ye sahip olduğu için ördek yazımı oraya girer, ancak sadece bir tanesi doğrudur. Ayrıca, bazen başka birinin kodunu koruyorum ve ne tür bir nesneyi geçtiğimi bilmiyorum. Bu, Python gibi dinamik olarak yazılmış dillerdeki en büyük sorunum. Sürüm 1 çok kolay ve hızlı bir şekilde geliştirilebilir. Sürüm 2 çöreklerdeki bir acıdır, özellikle sürüm 1'i yazmadıysanız. Bazen, yazmadığım bir işlevle çalışırken, bir parametrenin türünü bilmem gerekir,

__class__Parametrenin devreye girdiği yer burasıdır . (Anlayabildiğim kadarıyla), bir nesnenin türünü almanın en iyi yoludur (belki de tek yol).


2

Kullanın isinstance(object, type). Yukarıdaki gibi, doğru olduğunu biliyorsanız type, örneğin kullanımı kolaydır.

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

Ancak daha ezoterik nesneler için bu kullanımı zor olabilir. Örneğin:

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

ama bu numarayı yapabilirsiniz:

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

Bu nedenle y, kontrol etmek istediğiniz nesne türüyle (örneğin, type(np.array())) bir değişkenin ( bu durumda) başlatılmasını ve daha sonra kullanılmasını öneririm isinstance.


0

Kontrol seviyesi için sınıfları karşılaştırabilirsiniz.

#!/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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.