Come confrontare il tipo di un oggetto in Python?


163

Fondamentalmente voglio fare questo:

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

Provai:

type ( obj ) == type ( string )

e non ha funzionato.

Inoltre, che dire degli altri tipi? Ad esempio, non ho potuto replicare NoneType.


Funzionatype(obj) == str
Joshua Varghese il

Risposte:


241
isinstance()

Nel tuo caso, isinstance("this is a string", str)tornerà True.

Potresti anche voler leggere questo: http://www.canonical.org/~kragen/isinstance/


4
Direi che tu (il PO) dovresti assolutamente leggere il link di riferimento, che fornisce molti dettagli sul perché controllare il tipo di un oggetto è di solito una cattiva idea e cosa probabilmente dovresti fare invece.
Jeff Shannon,

2
dovresti usare basestr, non str. altrimenti non sceglierai Unicode. (anche se per 3.x Credo str è il basestr)
Hasen

36

isinstance lavori:

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

ma tieni a mente: se sembra un'anatra e se sembra un'anatra, è un'anatra.

EDIT: per il tipo None, puoi semplicemente fare:

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) Ciò restituisce un "1" anziché "No". Come aggirare questo?
dig_123,

Se si desidera utilizzare, isinstancema controllare anche per Nonequindi isinstance(obj, (MyClass, type(None)))funziona. types.NoneTypeè stato rimosso da Python 3, quindi non è portatile come type(None)ottenere un riferimento NoneType.
Santeri Paavolainen,

33

Innanzitutto, evitare tutti i confronti di tipo. Sono molto, molto raramente necessari. A volte, aiutano a controllare i tipi di parametri in una funzione - anche questo è raro. I dati di tipo errato genereranno un'eccezione, ed è tutto ciò di cui avrete bisogno.

Tutte le funzioni di conversione di base verranno mappate come uguali alla funzione di tipo.

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

Ci sono alcuni altri casi.

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

Nessuno, a proposito, non ha mai bisogno di questo tipo di controllo del tipo. None è l'unica istanza di NoneType. L'oggetto None è un Singleton. Controlla Nessuno

variable is None

A proposito, non utilizzare quanto sopra in generale. Usa le eccezioni ordinarie e il polimorfismo naturale di Python.


3
Se stai convalidando input da un DSL, hai bisogno di tutto questo, anche NoneType. Cosa succede se un parametro può essere una str, unicodeo None? isinstance(x, (str, unicode, types.NoneType))è molto più pulito del controllo None. Se stai costruendo strumenti per il calcolo differito o se stai per avviare un processo lungo o ad alta intensità di risorse, è utile rilevare gli typeerrori in anticipo, durante alcune fasi di convalida personalizzate. Questa è stata una parte fondamentale di quasi tutti i progetti di informatica scientifica su cui abbia mai lavorato. Di tutti i progetti di sviluppo che ho visto, ne sono serviti più di quanti non ne abbiano mai avuti.
ely,

23

Per altri tipi, controlla il modulo tipi :

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

PS Il typechecking è una cattiva idea.


15

Puoi sempre usare il type(x) == type(y)trucco, dove si ytrova qualcosa di tipo noto.

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

Spesso ci sono modi migliori per farlo, in particolare con qualsiasi pitone recente. Ma se vuoi solo ricordare una cosa, puoi ricordare quella.

In questo caso, i modi migliori sarebbero:

# 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

Nota l'ultimo caso: esiste solo un'istanza di NoneTypein Python, e cioè None. Vedrai NoneType molto nelle eccezioni (TypeError: 'NoneType' object is unsubscriptable - succede sempre a me ..) ma non dovrai quasi mai farvi riferimento nel codice.

Infine, come sottolinea Fengshaun, il controllo del tipo in Python non è sempre una buona idea. È più pitonico usare il valore come se fosse il tipo che ti aspetti e catturare (o consentire di propagare) le eccezioni che ne derivano.


1
Per quello che vale, isinstance () è il modo preferito di controllare i tipi in Python (quando devi farlo).
David Z,

6

Sei molto vicino! stringè un modulo, non un tipo. Probabilmente vuoi confrontare il tipo di objcon l'oggetto type per le stringhe, vale a dire str:

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

In alternativa:

type(obj) == type('')

Nota, in Python 2, se objè un tipo unicode, nessuna delle precedenti funzionerà. Né lo farà isinstance(). Vedi i commenti di John a questo post su come aggirare questo ... Sto provando a ricordarlo da circa 10 minuti ormai, ma ho avuto un blocco di memoria!


2
Usa basestring con isinstance () per ottenere sia str che unicode.
John Fouhy,

5

È perché devi scrivere

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

type accetta un'istanza e ne restituisce il tipo. In questo caso devi confrontare i tipi di due istanze.

Se è necessario eseguire un controllo preventivo, è meglio verificare un'interfaccia supportata rispetto al tipo.

Il tipo non ti dice molto, a parte il fatto che il tuo codice vuole un'istanza di un tipo specifico, indipendentemente dal fatto che potresti avere un'altra istanza di un tipo completamente diverso che andrebbe perfettamente bene perché implementa la stessa interfaccia .

Ad esempio, supponiamo di avere questo codice

def firstElement(parameter):
    return parameter[0]

Supponiamo che tu dica: voglio che questo codice accetti solo una tupla.

import types

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

Questo sta riducendo la riusabilità di questa routine. Non funzionerà se si passa un elenco, una stringa o un numpy.array. Qualcosa di meglio sarebbe

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

ma non ha senso farlo: il parametro [0] solleverà un'eccezione se il protocollo non è soddisfatto comunque ... questo ovviamente a meno che tu non voglia prevenire effetti collaterali o dover recuperare da chiamate che potresti invocare prima di fallire. Esempio (stupido), solo per chiarire il punto:

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 questo caso, il codice genererà un'eccezione prima di eseguire la chiamata di sistema (). Senza i controlli dell'interfaccia, avresti rimosso il file e quindi sollevato l'eccezione.


Grazie per aver indicato l'attuale modo preferito di verificare le interfacce. Molte delle risposte qui lo menzionano, ma pochi forniscono esempi di ciò che è buono invece. Non risponde ancora direttamente alla mia domanda personale (sto cercando di separare un elenco di stringhe, contenente molti elementi significativi, da una stringa che contiene molti elementi non significativi. Grazie!
Nick,

5

Usa str invece di string

type ( obj ) == str

Spiegazione

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

4

Io uso type(x) == type(y)

Ad esempio, se voglio controllare qualcosa è un array:

type( x ) == type( [] )

controllo delle stringhe:

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

Se si desidera verificare contro Nessuno, utilizzare è

x is None

eh? perché è una cattiva idea in generale? È solo una cattiva idea per le stringhe (per la versione 3.0) perché ci sono due tipi di stringhe, str e unicode. Per gli array, è una buona idea imho.
hasen

@hasen: è una cattiva idea nel complesso. Cosa succede se definisco il mio tipo che si comporta come un array ma, per esempio, recupera i valori da un database? Il tuo codice fallirà con il mio tipo senza motivo.
nosklo,

@hasen: leggi il link canonical.org/~kragen/isinstance della risposta più votata (+7), di voltronw
nosklo,

1
Bene, l'intero motivo (per me almeno) nel controllo del tipo è esattamente perché voglio trattare le matrici in modo diverso rispetto ad altri tipi (compresi i tipi che imitano le matrici).
hasen

2
Hai torto. Ti darò un esempio concreto: django ha un collegamento per il rendering del modello che può accettare una stringa o una matrice di stringhe. Ora, sia le stringhe che le matrici (elenchi) sono iterabili, ma in questo caso le funzioni devono differenziarsi.
hasen

2

penso che questo dovrebbe farlo

if isinstance(obj, str)

2

Il tipo non funziona su determinate classi. Se non si è sicuri del tipo di oggetto, utilizzare il __class__metodo, in questo modo:

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

Vedi anche questo articolo - http://www.siafoo.net/article/56


2

Per ottenere il tipo, utilizzare il __class__membro, come inunknown_thing.__class__

Parlare di scrivere anatre è inutile qui perché non risponde a una domanda perfettamente valida. Nel mio codice dell'applicazione non ho mai bisogno di conoscere il tipo di qualcosa, ma è comunque utile avere un modo per imparare il tipo di un oggetto. A volte ho bisogno di ottenere la classe effettiva per convalidare un test unitario. La digitazione di anatre si intromette perché tutti gli oggetti possibili hanno la stessa API, ma solo uno è corretto. Inoltre, a volte mantengo il codice di qualcun altro e non ho idea del tipo di oggetto che mi è stato passato. Questo è il mio più grande problema con linguaggi tipicamente dinamici come Python. La versione 1 è molto semplice e veloce da sviluppare. La versione 2 è un dolore nei panini, soprattutto se non hai scritto la versione 1. Quindi a volte, quando lavoro con una funzione che non ho scritto, devo conoscere il tipo di un parametro,

Ecco dove il __class__parametro è utile. Questo (per quanto ne so) è il modo migliore (forse l'unico modo) per ottenere il tipo di un oggetto.


2

Usa isinstance(object, type). Come sopra questo è facile da usare se si conosce il corretto type, ad es.

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

Ma per oggetti più esoterici, questo può essere difficile da usare. Per esempio:

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

ma puoi fare questo trucco:

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

Quindi consiglio di creare un'istanza di una variabile ( yin questo caso) con un tipo di oggetto che si desidera verificare (ad es. type(np.array())), Quindi utilizzare isinstance.


0

È possibile confrontare le classi per il livello di controllo.

#!/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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.