¿Hay una manera simple de determinar si una variable es una lista, un diccionario u otra cosa? Estoy recuperando un objeto que puede ser de cualquier tipo y necesito poder notar la diferencia.
python
dictionary
types
typeof
Justin Ethier
fuente
fuente
try
no ayuda. Por ejemplo, si sabía que un usuario podía pasar una cadena o una matriz, ambos son indexables, pero ese índice significa algo completamente diferente. Simplemente confiar en un try-catch en esos casos fallará de manera inesperada y extraña. Una solución es hacer un método separado, otra para agregar una pequeña comprobación de tipos. Yo personalmente prefiero comportamiento polimórfico a través de múltiples métodos que hacen casi lo mismo ... pero eso es sólo conmigo :)Respuestas:
Hay dos funciones integradas que lo ayudan a identificar el tipo de un objeto. Puede usarlo
type()
si necesita el tipo exacto de un objeto, yisinstance()
para verificar el tipo de un objeto contra algo. Por lo general, desea usar laisistance()
mayoría de las veces ya que es muy robusto y también admite la herencia de tipos.Para obtener el tipo real de un objeto, utiliza la
type()
función incorporada. Pasar un objeto como el único parámetro devolverá el tipo de objeto de ese objeto:Por supuesto, esto también funciona para tipos personalizados:
Tenga en cuenta que
type()
solo devolverá el tipo inmediato del objeto, pero no podrá informarle sobre la herencia de tipos.Para cubrir eso, debes usar la
isinstance
función. Por supuesto, esto también funciona para los tipos incorporados:isinstance()
suele ser la forma preferida de asegurar el tipo de un objeto porque también aceptará tipos derivados. Por lo tanto, a menos que realmente necesite el objeto type (por cualquier razón),isinstance()
se prefiere usartype()
.El segundo parámetro de
isinstance()
también acepta una tupla de tipos, por lo que es posible verificar múltiples tipos a la vez.isinstance
luego devolverá verdadero, si el objeto es de cualquiera de esos tipos:fuente
is
lugar de==
como los tipos son singletonsisinstance
es la forma preferida de todos modos, por lo que ninguno==
ois
se necesita usar.type
es la mejor respuesta. Hay momentos en queisinstance
es la mejor respuesta y hay momentos en que escribir pato es la mejor respuesta. Es importante conocer todas las opciones para poder elegir cuál es más apropiado para la situación.type(foo) is SomeType
que sería mejor queisinstance(foo, SomeType)
.isinstance
para tu caso de uso (verificar una variedad de tipos), y con como una sintaxis limpia, que tiene la gran ventaja de que puede capturar subclases. alguien que useOrderedDict
odiaría que su código fallara porque solo acepta dictados puros.Puedes hacerlo usando
type()
:fuente
Podría ser más Pythonic usar un
try
...except
bloque. De esa manera, si tiene una clase que grazna como una lista, o grazna como un dict, se comportará correctamente independientemente de cuál sea realmente su tipo .Para aclarar, el método preferido para "decir la diferencia" entre los tipos de variables es con algo llamado pato escribiendo : siempre que los métodos (y los tipos de retorno) a los que responde una variable sean lo que su subrutina espera, trátelo como lo espera. ser - estar. Por ejemplo, si tiene una clase que sobrecarga los operadores de corchetes con
getattr
ysetattr
, pero usa algún esquema interno divertido, sería apropiado que se comportara como un diccionario si eso es lo que está tratando de emular.El otro problema con la
type(A) is type(B)
comprobación es que siA
es una subclase deB
, se evalúafalse
cuándo, programáticamente, esperaría que lo fueratrue
. Si un objeto es una subclase de una lista, debería funcionar como una lista: verificar el tipo como se presenta en la otra respuesta evitará esto. (isinstance
funcionará, sin embargo).fuente
try
...except
es una buena solución cuando quiere lidiar con errores, pero no cuando decide un comportamiento basado en el tipo.En instancias de objeto también tiene el:
atributo. Aquí hay una muestra tomada de la consola Python 3.3
Tenga en cuenta que en python 3.xy en las clases New-Style (disponibles opcionalmente desde Python 2.6), la clase y el tipo se han fusionado y esto a veces puede conducir a resultados inesperados. Principalmente por esta razón, mi forma favorita de probar tipos / clases es con la función integrada isinstance .
fuente
__class__
en su mayoría está bien en Python 2.x, los únicos objetos en Python que no tienen__class__
atributo son las clases de estilo antiguo AFAIK. Por cierto, no entiendo su preocupación de Python 3: en tal versión, solo cada objeto tiene un__class__
atributo que apunta a la clase adecuada.Determinar el tipo de un objeto Python
Determine el tipo de un objeto con
type
Aunque funciona, evite los atributos de subrayado doble como
__class__
: no son semánticamente públicos y, aunque tal vez no en este caso, las funciones integradas suelen tener un mejor comportamiento.verificación de tipo
Bueno, esa es una pregunta diferente, no use type - use
isinstance
:Esto cubre el caso en el que su usuario podría estar haciendo algo inteligente o sensato al subclasificar
str
, de acuerdo con el principio de la sustitución de Liskov, desea poder usar instancias de subclase sin romper su código, y loisinstance
admite.Usa abstracciones
Aún mejor, puede buscar una clase base abstracta específica de
collections
onumbers
:O simplemente no explícitamente la verificación de tipo
O, quizás lo mejor de todo, utilice la escritura de pato y no verifique explícitamente su código. La escritura de patos admite la sustitución de Liskov con más elegancia y menos verbosidad.
Conclusión
type
para obtener realmente la clase de una instancia.isinstance
para verificar explícitamente las subclases reales o las abstracciones registradas.fuente
try
/ enexcept
lugar de verificar explícitamente.Puedes usar
type()
oisinstance()
.Tenga en cuenta que puede clobber
list
o cualquier otro tipo asignando una variable en el alcance actual del mismo nombre.Arriba vemos que
dict
se reasigna a una cadena, por lo tanto, la prueba:... falla
Para evitar esto y usarlo con
type()
más precaución:fuente
dict
cadena también fallará para muchos otros códigos, comodict([("key1", "value1"), ("key2", "value2")])
. La respuesta para ese tipo de problemas es "Entonces no hagas eso" . No sombree los nombres de tipos incorporados y espere que las cosas funcionen correctamente.Si bien las preguntas son bastante antiguas, me topé con esto mientras descubría una forma adecuada por mí mismo, y creo que aún necesita aclaraciones, al menos para Python 2.x (no comprobé Python 3, pero dado que el problema surge con las clases clásicas) que se han ido en tal versión, probablemente no importa).
Aquí estoy tratando de responder la pregunta del título: ¿cómo puedo determinar el tipo de un objeto arbitrario ? Otras sugerencias sobre el uso o no uso de isinstance están bien en muchos comentarios y respuestas, pero no estoy abordando esas preocupaciones.
El problema principal con el
type()
enfoque es que no funciona correctamente con instancias de estilo antiguo :Ejecutar este fragmento produciría:
Lo cual, sostengo, no es lo que la mayoría de la gente esperaría.
El
__class__
enfoque es el más cercano a la corrección, pero no funcionará en un caso crucial: cuando el objeto pasado es una clase de estilo antiguo (¡no una instancia!), Ya que esos objetos carecen de dicho atributo.Este es el fragmento de código más pequeño que se me ocurre que satisface una pregunta tan legítima de manera consistente:
fuente
tenga cuidado al usar isinstance
pero escribe
fuente
Como un aparte de las respuestas anteriores, vale la pena mencionar que la existencia
collections.abc
contiene varias clases base abstractas (ABC) que complementan la tipificación de pato.Por ejemplo, en lugar de verificar explícitamente si algo es una lista con:
podría, si solo le interesa ver si el objeto que tiene permite obtener elementos, use
collections.abc.Sequence
:si está estrictamente interesado en los objetos que permiten obtener, configurar y eliminar elementos (es decir, secuencias mutables ), optaría por
collections.abc.MutableSequence
.Muchas otras ABC se definen allí,
Mapping
para los objetos que se pueden utilizar como mapas,Iterable
,Callable
, etcétera. Se puede ver una lista completa de todos estos en la documentación decollections.abc
.fuente
En general, puede extraer una cadena de objeto con el nombre de la clase,
y usándolo para comparar
fuente
En muchos casos prácticos en lugar de usar
type
oisinstance
también puede usar@functools.singledispatch
, que se usa para definir funciones genéricas ( función compuesta de múltiples funciones que implementan la misma operación para diferentes tipos ).En otras palabras, querrá usarlo cuando tenga un código como el siguiente:
Aquí hay un pequeño ejemplo de cómo funciona:
Además, podemos usar clases abstractas para cubrir varios tipos a la vez:
fuente
type()
es una mejor solución queisinstance()
, particularmente parabooleans
:True
yFalse
son solo palabras clave que significan1
y0
en python. Así,y
ambos regresan
True
. Ambos booleanos son una instancia de un entero.type()
, sin embargo, es más inteligente:vuelve
False
.fuente