Pregunta Determinar el tipo de un objeto?


¿Hay una forma simple de determinar si una variable es una lista, un diccionario o alguna otra cosa? Recupero un objeto que puede ser del tipo y necesito poder notar la diferencia.


1378
2018-02-08 21:37


origen


Respuestas:


Para obtener el tipo de un objeto, puede usar el built-in type() función. Pasar un objeto como el único parámetro devolverá el tipo de objeto de ese objeto:

>>> type([]) is list
True
>>> type({}) is dict
True
>>> type('') is str
True
>>> type(0) is int
True
>>> type({})
<type 'dict'>
>>> type([])
<type 'list'>

Esto, por supuesto, también funciona para tipos personalizados:

>>> class Test1 (object):
        pass
>>> class Test2 (Test1):
        pass
>>> a = Test1()
>>> b = Test2()
>>> type(a) is Test1
True
>>> type(b) is Test2
True

Tenga en cuenta que type() solo devolverá el tipo de objeto inmediato, pero no podrá informarle acerca de la herencia de tipo.

>>> type(b) is Test1
False

Para cubrir eso, debes usar isinstance función. Esto, por supuesto, también funciona para tipos incorporados:

>>> isinstance(b, Test1)
True
>>> isinstance(b, Test2)
True
>>> isinstance(a, Test1)
True
>>> isinstance(a, Test2)
False
>>> isinstance([], list)
True
>>> isinstance({}, dict)
True

isinstance() generalmente es la forma preferida de garantizar el tipo de objeto porque también aceptará tipos derivados. A menos que realmente necesite el objeto tipo (por cualquier razón), use isinstance() es preferido sobre type().

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á true, si el objeto es de cualquiera de esos tipos:

>>> isinstance([], (tuple, list, set))
True

1603
2018-02-08 21:40



Puedes hacer eso usando type():

>>> a = []
>>> type(a)
<type 'list'>
>>> f = ()
>>> type(f)
<type 'tuple'>

141
2018-02-08 21:39



Podría ser más Pythonic usar un try...except bloquear. De esta forma, si tienes una clase que grazna como una lista, o graznidos como un dict, se comportará correctamente independientemente de su tipo De Verdad es.

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 tipos de devolución) a los que responde una variable sean los esperados por su subrutina, trátelos como usted espera. Por ejemplo, si tiene una clase que sobrecarga los operadores de soporte con getattr y setattr, pero usa algún esquema interno divertido, sería apropiado que se comporte como un diccionario si eso es lo que intenta emular.

El otro problema con el type(A) is type(B) comprobar es que si A es una subclase de B, evalúa false cuando, programáticamente, esperarías que fuera true. Si un objeto es una subclase de una lista, debería funcionar como una lista: al verificar el tipo como se presenta en la otra respuesta se evitará esto. (isinstance funcionará, sin embargo).


37
2018-02-08 21:43



En instancias de objeto, también tiene:

__class__

atributo. Aquí hay una muestra tomada de la consola de Python 3.3

>>> str = "str"
>>> str.__class__
<class 'str'>
>>> i = 2
>>> i.__class__
<class 'int'>
>>> class Test():
...     pass
...
>>> a = Test()
>>> a.__class__
<class '__main__.Test'>

Tenga en cuenta que en python 3.xy en las clases de estilo nuevo (opcionalmente de Python 2.6), la clase y el tipo se han fusionado y esto puede llevar a resultados inesperados. Principalmente por esta razón, mi forma favorita de probar tipos / clases es a la isinstance función incorporada.


30
2018-06-26 21:38



Determine el tipo de un objeto de Python

Determine el tipo de un objeto con type

>>> obj = object()
>>> type(obj)
<class 'object'>

Aunque funciona, evita los atributos del doble guión bajo como __class__ - no son semánticamente públicos, y, aunque tal vez no en este caso, las funciones integradas suelen tener un mejor comportamiento.

>>> obj.__class__ # avoid this!
<class 'object'>

tipo de comprobación

¿Hay una forma simple de determinar si una variable es una lista, un diccionario o alguna otra cosa? Recupero un objeto que puede ser del tipo y necesito poder notar la diferencia.

Bueno, esa es una pregunta diferente, no use tipo - use isinstance:

def foo(obj):
    """given a string with items separated by spaces, 
    or a list or tuple, 
    do something sensible
    """
    if isinstance(obj, str):
        obj = str.split()
    return _foo_handles_only_lists_or_tuples(obj)

Esto cubre el caso en que su usuario podría estar haciendo algo inteligente o sensato al crear subclases str - de acuerdo con el principio de la sustitución Liskov, quiere poder usar instancias de subclases sin romper su código - y isinstance apoya esto

Usa abstracciones

Mejor aún, puede buscar una clase base abstracta específica de collections o numbers:

from collections import Iterable
from numbers import Number

def bar(obj):
    """does something sensible with an iterable of numbers, 
    or just one number
    """
    if isinstance(obj, Number): # make it a 1-tuple
        obj = (obj,)
    if not isinstance(obj, Iterable):
        raise TypeError('obj must be either a number or iterable of numbers')
    return _bar_sensible_with_iterable(obj)

O simplemente no explíqueme explícitamente

O, lo mejor de todo, use pato-tipado y no verifique explícitamente su código. Duck-typing admite la sustitución de Liskov con más elegancia y menos verbosidad.

def baz(obj):
    """given an obj, a dict (or anything with an .items method) 
    do something sensible with each key-value pair
    """
    for key, value in obj.items():
        _baz_something_sensible(key, value)

Conclusión

  • Utilizar type para obtener realmente una clase de instancia.
  • Utilizar isinstance para verificar explícitamente las subclases reales o las abstracciones registradas.
  • Y simplemente evite el tipeo cuando tenga sentido.

14
2018-03-14 21:12



Puedes usar type() o isinstance().

>>> type([]) is list
True

Ten en cuenta que puedes golpear list o cualquier otro tipo asignando una variable en el alcance actual del mismo nombre.

>>> the_d = {}
>>> t = lambda x: "aight" if type(x) is dict else "NOPE"
>>> t(the_d) 'aight'
>>> dict = "dude."
>>> t(the_d) 'NOPE'

Arriba vemos que dict se reasigna a una cadena, por lo tanto, la prueba:

type({}) is dict

... falla

Para evitar esto y usar type() más cautelosamente

>>> import __builtin__
>>> the_d = {}
>>> type({}) is dict
True
>>> dict =""
>>> type({}) is dict
False
>>> type({}) is __builtin__.dict
True

10
2018-05-31 21:57



Si bien las preguntas son bastante antiguas, me encontré con esto al mismo tiempo que descubrí una manera adecuada, y creo que todavía necesita aclaración, al menos para Python 2.x (no verificó Python 3, pero dado que el problema surge con las clases clásicas que faltan en dicha versión, probablemente no importe).

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 la instancia 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 las instancias antiguas:

class One:
    pass

class Two:
    pass


o = One()
t = Two()

o_type = type(o)
t_type = type(t)

print "Are o and t instances of the same class?", o_type is t_type

Ejecutar este fragmento arrojaría:

Are o and t instances of the same class? True

Lo cual, sostengo, no es lo que la mayoría de la gente esperaría.

los __class__ enfoque es lo más cercano a la corrección, pero no funcionará en un caso crucial: cuando el objeto pasado es un viejo estilo clase (¡No es una instancia!), ya que esos objetos carecen de dicho atributo.

Este es el fragmento de código más pequeño que podría pensar que satisface esa pregunta legítima de manera consistente:

#!/usr/bin/env python
from types import ClassType
#we adopt the null object pattern in the (unlikely) case
#that __class__ is None for some strange reason
_NO_CLASS=object()
def get_object_type(obj):
    obj_type = getattr(obj, "__class__", _NO_CLASS)
    if obj_type is not _NO_CLASS:
        return obj_type
    # AFAIK the only situation where this happens is an old-style class
    obj_type = type(obj)
    if obj_type is not ClassType:
        raise ValueError("Could not determine object '{}' type.".format(obj_type))
    return obj_type

4
2018-06-17 08:35



Como un aparte de las respuestas anteriores, vale la pena mencionar la existencia de collections.abc que 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:

isinstance(my_obj, list)

podría, si solo está interesado en ver si el objeto que tiene le permite obtener artículos, use collections.abc.Sequence:

from collections.abc import Sequence
isinstance(my_obj, Sequence) 

si está estrictamente interesado en los objetos que permiten obtener, configurar y borrar elementos (es decir mudable secuencias), podrías optar por collections.abc.MutableSequence.

Muchos otros ABC se definen allí, Mapping para objetos que pueden usarse como mapas, Iterable, Callable, etcétera. Una lista completa de todos estos se puede ver en la documentación para collections.abc.


3
2017-12-07 15:50



tenga cuidado de usar isinstance

isinstance(True, bool)
True
>>> isinstance(True, int)
True

pero escribe

type(True) == bool
True
>>> type(True) == int
False

2
2017-11-14 11:22