¿Cómo comparar el tipo de un objeto en Python?

163

Básicamente quiero hacer esto:

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

Lo intenté:

type ( obj ) == type ( string )

Y no funcionó.

Además, ¿qué pasa con los otros tipos? Por ejemplo, no pude replicar NoneType.

Joan Venge
fuente
Esto funcionatype(obj) == str
Joshua Varghese

Respuestas:

241
isinstance()

En su caso, isinstance("this is a string", str)volveremos True.

También puede leer esto: http://www.canonical.org/~kragen/isinstance/

Antonio
fuente
44
Yo diría que usted (el OP) definitivamente debería leer el enlace al que se hace referencia, que brinda muchos detalles de por qué verificar el tipo de un objeto generalmente es una mala idea, y lo que probablemente debería estar haciendo en su lugar.
Jeff Shannon el
2
deberías usar basestr, no str. de lo contrario, no elegirá unicode. (aunque para 3.x creo que str es la base)
hasen
36

isinstance trabajos:

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

pero , tenga en cuenta: si parece un pato, y si suena como un pato, es un pato.

EDITAR: para el tipo Ninguno, simplemente puede hacer:

if obj is None: obj = MyClass()
fengshaun
fuente
def distance_from_zero(n): if isinstance(n,int) or isinstance(n,float): return abs(n) else: return "Nope" print distance_from_zero(True) Esto devuelve un "1" en lugar de "No". Cómo evitar esto ?
dig_123
Si desea utilizar, isinstancepero compruebe también para Noneentonces isinstance(obj, (MyClass, type(None)))funciona. types.NoneTypese ha eliminado de Python 3, por lo que no es tan portátil como type(None)para obtener una referencia NoneType.
Santeri Paavolainen
33

Primero, evite todas las comparaciones de tipos. Son muy, muy raramente necesarios. A veces, ayudan a verificar los tipos de parámetros en una función, incluso eso es raro. Los datos de tipo incorrecto generarán una excepción, y eso es todo lo que necesitará.

Todas las funciones básicas de conversión se asignarán como iguales a la función de tipo.

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

Hay algunos otros casos.

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

Ninguno, por cierto, nunca necesita este tipo de verificación de tipo. Ninguno es la única instancia de NoneType. El objeto None es un Singleton. Solo verifique Ninguno

variable is None

Por cierto, no utilice lo anterior en general. Use excepciones ordinarias y el propio polimorfismo natural de Python.

S.Lott
fuente
3
Si está validando entradas de un DSL, necesita todo esto, incluso NoneType. ¿Qué pasa si un parámetro puede ser una str, unicodeo None? isinstance(x, (str, unicode, types.NoneType))es mucho más limpio que buscarlo None. Si está creando herramientas para el cálculo diferido, o si está a punto de iniciar un proceso largo o que requiere muchos recursos, es valioso detectar los typeerrores con anticipación, durante algún paso de validación personalizado. Esta ha sido una parte crítica de casi todos los proyectos de computación científica en los que he trabajado. De todos los proyectos de desarrollo que he visto, más han necesitado esto que no.
ely
23

Para otros tipos, consulte el módulo de tipos :

>>> 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 es una mala idea.

Paolo Bergantino
fuente
15

Siempre puedes usar el type(x) == type(y)truco, donde yhay algo con un tipo conocido.

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

A menudo hay mejores formas de hacerlo, particularmente con cualquier python reciente. Pero si solo quieres recordar una cosa, puedes recordar eso.

En este caso, las mejores formas serían:

# 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

Tenga en cuenta el último caso: solo hay una instancia de NoneTypeen python, y esa es None. Verá NoneType mucho en las excepciones ( TypeError: 'NoneType' object is unsubscriptableme sucede todo el tiempo ...) pero casi nunca necesitará referirse a él en el código.

Finalmente, como señala fengshaun, la verificación de tipos en python no siempre es una buena idea. Es más pitónico usar el valor como si fuera el tipo que espera, y capturar (o permitir propagar) las excepciones que resultan de él.

John Fouhy
fuente
1
Por lo que vale, isinstance () es la forma preferida de verificar tipos en Python (cuando tiene que hacerlo).
David Z
6

Estás muy cerca! stringes un módulo, no un tipo. Probablemente desee comparar el tipo de objcontra el tipo de objeto para cadenas, a saber str:

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

Alternativamente:

type(obj) == type('')

Tenga en cuenta que, en Python 2, si objes un tipo Unicode, ninguno de los anteriores funcionará. Tampoco lo hará isinstance(). Vea los comentarios de John a esta publicación sobre cómo solucionar esto ... He estado tratando de recordarlo durante unos 10 minutos, ¡pero estaba teniendo un bloqueo de memoria!

Jarret Hardie
fuente
2
Use la cadena base con isinstance () para obtener str y unicode.
John Fouhy el
5

Es porque tienes que escribir

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

type acepta una instancia y devuelve su tipo. En este caso, debe comparar los tipos de dos instancias.

Si necesita hacer una verificación preventiva, es mejor si busca una interfaz compatible que el tipo.

El tipo realmente no le dice mucho, aparte del hecho de que su código desea una instancia de un tipo específico, independientemente del hecho de que podría tener otra instancia de un tipo completamente diferente que estaría perfectamente bien porque implementa la misma interfaz .

Por ejemplo, suponga que tiene este código

def firstElement(parameter):
    return parameter[0]

Ahora, suponga que dice: Quiero que este código acepte solo una tupla.

import types

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

Esto está reduciendo la reutilización de esta rutina. No funcionará si pasa una lista, o una cadena, o un numpy.array. Algo mejor seria

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

pero no tiene sentido hacerlo: el parámetro [0] generará una excepción si el protocolo no se cumple de todos modos ... esto, por supuesto, a menos que desee evitar efectos secundarios o tener que recuperarse de las llamadas que podría invocar antes de fallar. (Estúpido) ejemplo, solo para hacer el 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]

en este caso, su código generará una excepción antes de ejecutar la llamada system (). Sin las comprobaciones de la interfaz, habría eliminado el archivo y luego planteado la excepción.

Stefano Borini
fuente
Gracias por indicar la forma preferida real de verificar las interfaces. Muchas de las respuestas aquí lo mencionan, pero pocas dan ejemplos de lo que es bueno. Todavía no responde a mi pregunta personal directamente (estoy tratando de separar una lista de cadenas, que contiene muchos elementos significativos, de una cadena, que contiene muchos elementos no significativos. ¡Gracias!
Nick
5

Use str en lugar de string

type ( obj ) == str

Explicación

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

yo suelo type(x) == type(y)

Por ejemplo, si quiero verificar algo es una matriz:

type( x ) == type( [] )

verificación de cadena:

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

Si desea verificar con Ninguno, el uso es

x is None
Hasen
fuente
eh? ¿Por qué es una mala idea en general? Es solo una mala idea para las cadenas (para pre 3.0) porque hay dos tipos de cadenas, str y unicode. Para las matrices, es una buena idea en mi humilde opinión.
hasen
@hasen: es una mala idea en general. ¿Qué sucede si defino mi propio tipo que se comporta como una matriz pero, por ejemplo, obtiene valores de una base de datos? Su código fallará con mi tipo sin ninguna razón.
nosklo 03 de
@hasen: lea el enlace canonical.org/~kragen/isinstance de la respuesta más votada (+7), por voltronw
nosklo
1
Bueno, la razón completa (al menos para mí) para verificar el tipo es exactamente porque quiero tratar las matrices de manera diferente a otros tipos (incluidos los tipos que imitan las matrices).
hasen
2
Te equivocas. Le daré un ejemplo concreto: django tiene un atajo de representación de plantilla que puede aceptar una cadena o una matriz de cadenas. Ahora, tanto las cadenas como las matrices (listas) son iterables, pero en este caso, las funciones deben diferenciarse entre ellas.
hasen
2

creo que esto debería hacerlo

if isinstance(obj, str)
Aziz
fuente
2

El tipo no funciona en ciertas clases. Si no está seguro del tipo de objeto, use el __class__método, así:

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

Consulte también este artículo: http://www.siafoo.net/article/56

Toby Fernsler
fuente
2

Para obtener el tipo, use el __class__miembro, como enunknown_thing.__class__

Hablar de tipear patos es inútil aquí porque no responde una pregunta perfectamente buena. En mi código de aplicación, nunca necesito saber el tipo de algo, pero sigue siendo útil tener una manera de aprender el tipo de un objeto. A veces necesito obtener la clase real para validar una prueba unitaria. La escritura de pato se interpone en el camino porque todos los objetos posibles tienen la misma API, pero solo uno es correcto. Además, a veces mantengo el código de otra persona, y no tengo idea de qué tipo de objeto me han pasado. Este es mi mayor problema con lenguajes de tipo dinámico como Python. La versión 1 es muy fácil y rápida de desarrollar. La versión 2 es una molestia en los bollos, especialmente si no escribió la versión 1. Entonces, a veces, cuando estoy trabajando con una función que no escribí, necesito saber el tipo de parámetro,

Ahí es donde el __class__parámetro resulta útil. Esa (hasta donde puedo decir) es la mejor manera (tal vez la única forma) de obtener el tipo de un objeto.

Miguel Muñoz
fuente
2

Uso isinstance(object, type). Como se mencionó anteriormente, esto es fácil de usar si conoce la correcta type, por ejemplo,

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

Pero para objetos más esotéricos, esto puede ser difícil de usar. Por ejemplo:

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

pero puedes hacer este truco:

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

Por lo tanto, recomiendo crear una instancia de una variable ( yen este caso) con un tipo del objeto que desea verificar (por ejemplo, type(np.array())) y luego usar isinstance.

huesos de viaje
fuente
0

Puede comparar clases para verificar el nivel.

#!/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
quickes
fuente