Wie vergleiche ich den Typ eines Objekts in Python?


163

Grundsätzlich möchte ich das machen:

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

Ich habe es versucht:

type ( obj ) == type ( string )

und es hat nicht funktioniert.

Und was ist mit den anderen Typen? Zum Beispiel konnte ich nicht replizieren NoneType.


Dies funktionierttype(obj) == str
Joshua Varghese

Antworten:


241
isinstance()

In Ihrem Fall isinstance("this is a string", str)wird zurückkehren True.

Vielleicht möchten Sie auch Folgendes lesen: http://www.canonical.org/~kragen/isinstance/


4
Ich würde sagen, Sie (das OP) sollten auf jeden Fall den Link lesen, auf den verwiesen wird. Dieser enthält viele Details darüber, warum das Überprüfen des Objekttyps normalerweise eine schlechte Idee ist und was Sie wahrscheinlich stattdessen tun sollten.
Jeff Shannon

2
Sie sollten basestr verwenden, nicht str. Andernfalls wählen Sie keinen Unicode. (obwohl für 3.x denke ich str ist die basestr)
hasen

36

isinstance funktioniert:

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

Aber denken Sie daran: Wenn es wie eine Ente aussieht und wenn es wie eine Ente klingt, ist es eine Ente.

BEARBEITEN: Für den Typ Keine können Sie einfach Folgendes tun:

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) Dies gibt eine "1" anstelle von "Nope" zurück. Wie kann man das umgehen?
dig_123

Wenn Sie verwenden möchten, isinstanceaber auch prüfen, funktioniert Nonedann isinstance(obj, (MyClass, type(None))). types.NoneTypewurde aus Python 3 entfernt, daher ist es nicht so portabel, als type(None)dass ein Verweis darauf abgerufen werden könnte NoneType.
Santeri Paavolainen

33

Vermeiden Sie zunächst alle Typvergleiche. Sie sind sehr, sehr selten notwendig. Manchmal helfen sie dabei, Parametertypen in einer Funktion zu überprüfen - auch das ist selten. Falsche Typdaten lösen eine Ausnahme aus, und das ist alles, was Sie jemals brauchen werden.

Alle grundlegenden Konvertierungsfunktionen werden der Typfunktion gleich zugeordnet.

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

Es gibt noch einige andere Fälle.

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

Übrigens braucht keiner diese Art der Typprüfung. None ist die einzige Instanz von NoneType. Das None-Objekt ist ein Singleton. Überprüfen Sie einfach auf Keine

variable is None

Übrigens, verwenden Sie die oben genannten im Allgemeinen nicht. Verwenden Sie gewöhnliche Ausnahmen und Pythons eigenen natürlichen Polymorphismus.


3
Wenn Sie Eingaben von einem DSL validieren, benötigen Sie all dies sogar NoneType. Was passiert , wenn ein Parameter kann eine sein str, unicodeoder None? isinstance(x, (str, unicode, types.NoneType))ist viel sauberer als zu überprüfen None. Wenn Sie Tools für verzögerte Berechnungen erstellen oder einen langen oder ressourcenintensiven Prozess starten möchten, ist es hilfreich, typeFehler während eines benutzerdefinierten Validierungsschritts im Voraus zu erkennen. Dies war ein wichtiger Bestandteil fast aller wissenschaftlichen Computerprojekte, an denen ich jemals gearbeitet habe. Von allen Entwicklungsprojekten, die ich gesehen habe, haben mehr dies benötigt als nicht.
Ely

23

Weitere Typen finden Sie im Modul Typen :

>>> 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 ist eine schlechte Idee.


15

Sie können immer den type(x) == type(y)Trick verwenden, wo yetwas mit bekanntem Typ ist.

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

Oft gibt es dafür bessere Möglichkeiten, insbesondere bei neueren Pythons. Aber wenn Sie sich nur an eine Sache erinnern wollen, können Sie sich daran erinnern.

In diesem Fall wären die besseren Möglichkeiten:

# 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

Beachten Sie den letzten Fall: Es gibt nur eine Instanz von NoneTypein Python, und das ist None. Sie werden NoneType häufig in Ausnahmen sehen ( TypeError: 'NoneType' object is unsubscriptable- passiert mir die ganze Zeit ..), aber Sie müssen kaum jemals im Code darauf verweisen.

Wie Fengshaun betont, ist die Typprüfung in Python nicht immer eine gute Idee. Es ist pythonischer, den Wert einfach so zu verwenden, als wäre er der erwartete Typ, und die daraus resultierenden Ausnahmen abzufangen (oder zu verbreiten).


1
Für das, was es wert ist, ist isinstance () die bevorzugte Methode, um Typen in Python zu überprüfen (wenn Sie es tun müssen).
David Z

6

Du bist sehr nah! stringist ein Modul, kein Typ. Sie möchten wahrscheinlich den Typ von objmit dem Typobjekt für Zeichenfolgen vergleichen, nämlich str:

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

Alternative:

type(obj) == type('')

Beachten Sie, dass in Python 2, wenn objes sich um einen Unicode-Typ handelt, keines der oben genannten Verfahren funktioniert. Auch nicht isinstance(). In Johns Kommentaren zu diesem Beitrag erfahren Sie, wie Sie das umgehen können ... Ich habe seit ungefähr 10 Minuten versucht, mich daran zu erinnern, hatte aber einen Speicherblock!


2
Verwenden Sie basestring mit isinstance (), um sowohl str als auch unicode abzurufen.
John Fouhy

5

Es ist, weil Sie schreiben müssen

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

Typ akzeptiert eine Instanz und gibt ihren Typ zurück. In diesem Fall müssen Sie die Typen zweier Instanzen vergleichen.

Wenn Sie eine vorbeugende Prüfung durchführen müssen, ist es besser, wenn Sie nach einer unterstützten Schnittstelle suchen als nach dem Typ.

Der Typ sagt nicht wirklich viel aus, abgesehen von der Tatsache, dass Ihr Code eine Instanz eines bestimmten Typs möchte, unabhängig davon, dass Sie eine andere Instanz eines völlig anderen Typs haben könnten, was vollkommen in Ordnung wäre, da es dieselbe Schnittstelle implementiert .

Angenommen, Sie haben diesen Code

def firstElement(parameter):
    return parameter[0]

Angenommen, Sie sagen: Ich möchte, dass dieser Code nur ein Tupel akzeptiert.

import types

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

Dies verringert die Wiederverwendbarkeit dieser Routine. Es funktioniert nicht, wenn Sie eine Liste, einen String oder ein numpy.array übergeben. Etwas besseres wäre

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

Aber es macht keinen Sinn, dies zu tun: Parameter [0] löst eine Ausnahme aus, wenn das Protokoll ohnehin nicht erfüllt ist ... dies natürlich, es sei denn, Sie möchten Nebenwirkungen verhindern oder müssen sich von Aufrufen erholen, die Sie aufrufen könnten, bevor Sie fehlschlagen. (Dummes) Beispiel, nur um den Punkt zu machen:

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

In diesem Fall löst Ihr Code eine Ausnahme aus, bevor der system () -Aufruf ausgeführt wird. Ohne Schnittstellenprüfungen hätten Sie die Datei entfernt und dann die Ausnahme ausgelöst.


Vielen Dank, dass Sie den bevorzugten Weg zur Überprüfung auf Schnittstellen angegeben haben. Viele der Antworten hier erwähnen es, aber nur wenige geben Beispiele dafür, was stattdessen gut ist. Es beantwortet meine persönliche Frage immer noch nicht direkt (ich versuche, eine Liste von Zeichenfolgen, die viele bedeutungsvolle Elemente enthalten, von einer Zeichenfolge zu trennen, die viele nicht aussagekräftige Elemente enthält. Danke!
Nick

5

Verwenden Sie str anstelle von string

type ( obj ) == str

Erläuterung

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

4

ich benutze type(x) == type(y)

Wenn ich zum Beispiel etwas überprüfen möchte, handelt es sich um ein Array:

type( x ) == type( [] )

Zeichenfolgenprüfung:

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

Wenn Sie gegen Keine prüfen möchten, verwenden Sie

x is None

huh? Warum ist es im Allgemeinen eine schlechte Idee? Es ist nur eine schlechte Idee für Strings (für Pre 3.0), da es zwei Arten von Strings gibt, str und Unicode. Für Arrays ist es imho eine gute Idee.
hasen

@hasen: es ist insgesamt eine schlechte idee. Was ist, wenn ich meinen eigenen Typ definiere, der sich wie ein Array verhält, aber beispielsweise Werte aus einer Datenbank abruft? Ihr Code wird mit meinem Typ ohne Grund fehlschlagen.
Nosklo

@hasen: Lesen Sie den Link canonical.org/~kragen/isinstance der am häufigsten gewählten (+7) Antwort von voltronw
nosklo

1
Nun, der gesamte Grund (zumindest für mich) bei der Überprüfung des Typs liegt genau darin, dass ich mit Arrays anders umgehen möchte als mit anderen Typen (einschließlich Typen, die Arrays imitieren).
Hasen

2
Du liegst falsch. Ich gebe Ihnen ein konkretes Beispiel: django verfügt über eine Verknüpfung zum Rendern von Vorlagen, die entweder eine Zeichenfolge oder ein Array von Zeichenfolgen akzeptieren kann. Jetzt sind sowohl Zeichenfolgen als auch Arrays (Listen) iterierbar, aber in diesem Fall müssen die Funktionen zwischen ihnen unterscheiden.
Hasen

2

Ich denke, das sollte es tun

if isinstance(obj, str)

2

Typ funktioniert in bestimmten Klassen nicht. Wenn Sie sich über den Objekttyp nicht sicher sind, verwenden Sie die folgende __class__Methode:

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

Siehe auch diesen Artikel - http://www.siafoo.net/article/56


2

Verwenden Sie das __class__Element wie in, um den Typ abzurufenunknown_thing.__class__

Die Rede vom Ententippen ist hier nutzlos, weil es keine vollkommen gute Frage beantwortet. In meinem Anwendungscode muss ich nie den Typ von etwas kennen, aber es ist immer noch nützlich, eine Möglichkeit zu haben, den Typ eines Objekts zu lernen. Manchmal muss ich die tatsächliche Klasse erhalten, um einen Komponententest zu validieren. Die Eingabe von Enten wird dort behindert, da alle möglichen Objekte dieselbe API haben, aber nur eines korrekt ist. Außerdem pflege ich manchmal den Code eines anderen und habe keine Ahnung, welche Art von Objekt mir übergeben wurde. Dies ist mein größtes Problem mit dynamisch getippten Sprachen wie Python. Version 1 ist sehr einfach und schnell zu entwickeln. Version 2 ist ein Problem, besonders wenn Sie Version 1 nicht geschrieben haben. Wenn ich also mit einer Funktion arbeite, die ich nicht geschrieben habe, muss ich manchmal den Typ eines Parameters kennen.

Hier bietet sich der __class__Parameter an. Dies ist (soweit ich das beurteilen kann) der beste (vielleicht einzige) Weg, um den Typ eines Objekts zu ermitteln.


2

Verwenden Sie isinstance(object, type). Wie oben ist dies einfach zu verwenden, wenn Sie das richtige kennen type, z.

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

Bei esoterischeren Objekten kann dies jedoch schwierig zu verwenden sein. Beispielsweise:

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

Aber Sie können diesen Trick machen:

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

Daher empfehle ich, eine Variable ( yin diesem Fall) mit einem Typ des Objekts zu instanziieren, das Sie überprüfen möchten (z. B. type(np.array())), und dann zu verwenden isinstance.


0

Sie können Klassen für die Prüfstufe vergleichen.

#!/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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.