¿Cuál es la forma canónica de verificar el tipo en Python?

¿Cuál es la mejor forma de comprobar si un objeto determinado es de un tipo determinado? ¿Qué tal comprobar si el objeto hereda de un tipo determinado?

Digamos que tengo un objeto o. ¿Cómo verifico si es un str?

preguntado el 30 de septiembre de 08 a las 09:09

Bueno, el enfoque canónico en Python es no verificar el tipo en absoluto (a menos que esté depurando). Por lo general, solo intenta usarlo como una cadena (por ejemplo, concatenar con otras cadenas, imprimir en la consola, etc.); si cree que podría fallar, use try / except o hasattr. Dicho esto, la respuesta aceptada es la forma canónica de hacer lo que generalmente "no deberías hacer" en el mundo de Python. Para obtener más información, busque en Google "Python duck typing" o lea estos: voidspace.org.uk/python/articles/duck_typing.shtml stackoverflow.com/questions/610883/… -

Creo que el Sr. Coombs está pasando por alto ejemplos como clases serializables que no son JSON. Si se coloca una gran cantidad de datos a través de una función (en cuyo código no se puede influir), es posible que desee convertir ciertas partes de esos datos en, por ejemplo, una antes de pasarlo. Al menos así es como I terminó en esta página ... -

Parece que la razón más común para pedir esto es que uno quiere distinguir entre cadenas e iterables de cadenas. Esta es una pregunta delicada porque las cadenas se encuentran las iterables de cadenas: una cadena de un solo carácter es incluso una secuencia de sí misma (la última vez que verifiqué, probablemente uno no debería confiar en ella). Pero, ¿alguien alguna vez usaría algo parecido a una cuerda? . Entonces, la respuesta a "¿Qué debo hacer para distinguir entre cadenas y otros iterables de cadenas?" es correctamente: "Depende de lo que esté intentando hacer". :-D -

Las anotaciones de tipo Python ahora son una cosa. Echa un vistazo a mipy -

12 Respuestas

Para verificar si o es una instancia de str o cualquier subclase de str, Utilizar es instancia (esta sería la forma "canónica"):

if isinstance(o, str):

Para comprobar si el tipo de o es exactamente str (excluir subclases):

if type(o) is str:

Lo siguiente también funciona y puede ser útil en algunos casos:

if issubclass(type(o), str):

Vea Funciones integradas en la Referencia de la biblioteca de Python para obtener información relevante.

Una nota más: en este caso, si está utilizando Python 2, es posible que desee utilizar:

if isinstance(o, basestring):

porque esto también capturará cadenas Unicode (unicode no es una subclase de str; ambos str y unicode son subclases de basestring) Tenga en cuenta que basestring ya no existe en Python 3, donde hay una estricta separación de cuerdasstr) y datos binarios (bytes).

Alternativamente, isinstance acepta una tupla de clases. Esto volverá True if o es una instancia de cualquier subclase de cualquiera de (str, unicode):

if isinstance(o, (str, unicode)):

Respondido el 27 de enero de 20 a las 06:01

str .__ subclasses __ () solo devuelve las subclases directas de str, y no hace lo mismo que issubclass () o isinstance (). (Para hacer eso, tendría que llamar recursivamente .__ subclases __ (). - Tomás Wouters

Esta es una buena respuesta, pero creo que realmente debería comenzar con una advertencia de que normalmente no debería hacer esto en Python. Tal como está, parece validar la suposición de que esto es una "cosa canónica para hacer en Python", que no lo es. - jon coombs

¿Cuál es la diferencia entre instancia y "exactamente"? Si type(a) is Object entonces ¿no es también cierto que isinstance(a, Object). Sin embargo, si type(a) is SubClassOfObject, entonces type(a) is Object == False, pero isinstance(a, Object) == True. ¿Derecha? - mavavilj

@mavavilj - a is b significa que ayb son exactamente lo mismo, es decir, referencias a la misma entidad en la memoria. Entonces a y b tendría que ser exactamente la misma clase, no subclases, como con isinstance(). Ver por ejemplo stackoverflow.com/a/133024/1072212 - terry marrón

@JonCoombs Según la lógica de PEP 622, isinstance() es la segunda función incorporada más llamada, después len(). Creo que tenemos que aceptar eso isinstance es Python canónico de facto. - Bolígrafo Ben

La la mayor La forma pitónica de comprobar el tipo de un objeto es ... no comprobarlo.

Dado que Python anima Mecanografía de pato, deberías solo try...except para utilizar los métodos del objeto de la forma que desee utilizarlos. Entonces, si su función está buscando un objeto de archivo grabable, no comprueba que es una subclase de file, solo intenta usar su .write() ¡método!

Por supuesto, a veces estas bonitas abstracciones se rompen y isinstance(obj, cls) es lo que necesitas. Pero utilícelo con moderación.

Respondido el 10 de Septiembre de 18 a las 00:09

En mi humilde opinión, la forma más pitónica es hacer frente a cualquier argumento que se dé. En mi código, a menudo no puedo saber si recibo un objeto o una matriz de objetos, y utilizo la verificación de tipos internamente para convertir un solo objeto en una lista de un elemento. - Sastanin

En lugar de intentar usar su método de escritura, hay ocasiones en las que desea hacer esto sin causar una excepción. En este caso podrías hacer ... if hasattr(ob, "write") and callable(ob.write): O guarde un poco de acceso a dict ... func = getattr(ob, "write", None) if callable(func): ... - ideasman42

Mecanografiar pato se trata de usar una biblioteca. La verificación de tipo se trata de la escritura una biblioteca. No es el mismo dominio de problemas. - RickyA

@RickyA, no estoy de acuerdo. Duck typing se trata de interactuar con objetos utilizando interfaces con semántica conocida. Esto puede aplicarse al código de la biblioteca o al código que utiliza dicha biblioteca. - Dan Lenski

@ nyuszika7h, en Python3 hasattr solo suprime un AttributeError - Ver: docs.python.org/3.4/library/functions.html#hasattr - ideasman42

isinstance(o, str) regresará True if o es un str o es de un tipo que hereda de str.

type(o) is str regresará True si y solo si o es una str. Volverá False if o es de un tipo que hereda de str.

respondido 10 mar '19, 16:03

Por supuesto, esto fallará si el objeto no es una instancia de 'str', sino algo parecido a una cadena. Como unicode, mmap, UserString o cualquier otro tipo definido por el usuario. El enfoque habitual en Python es no realizar comprobaciones de tipo. - Tomás Wouters

Esto es muy útil. Porque la diferencia entre isinstance y type(var) == type('') no está claro. - Sastanin

Una vez formulada y respondida la pregunta, se agregaron sugerencias de tipo a Python. Las sugerencias de tipo en Python permiten verificar los tipos, pero de una manera muy diferente a los lenguajes escritos estáticamente. Las sugerencias de tipo en Python asocian los tipos esperados de argumentos con funciones como datos accesibles en tiempo de ejecución asociados con funciones y esto permite para comprobar los tipos. Ejemplo de sintaxis de sugerencia de tipo:

def foo(i: int):
    return i

foo(5)
foo('oops')

En este caso, queremos que se active un error para foo('oops') ya que el tipo anotado del argumento es int. La sugerencia de tipo agregada no porque se producirá un error cuando el script se ejecute normalmente. Sin embargo, agrega atributos a la función que describen los tipos esperados que otros programas pueden consultar y usar para verificar errores de tipo.

Uno de estos otros programas que se puede utilizar para encontrar el tipo de error es mypy:

mypy script.py
script.py:12: error: Argument 1 to "foo" has incompatible type "str"; expected "int"

(Es posible que deba instalar mypy desde su administrador de paquetes. No creo que venga con CPython, pero parece tener cierto nivel de "oficialidad").

La verificación de tipos de esta manera es diferente de la verificación de tipos en lenguajes compilados de tipo estático. Debido a que los tipos son dinámicos en Python, la verificación de tipos debe realizarse en tiempo de ejecución, lo que impone un costo, incluso en los programas correctos, si insistimos en que suceda en cada oportunidad. Las verificaciones de tipo explícitas también pueden ser más restrictivas de lo necesario y causar errores innecesarios (por ejemplo, ¿el argumento realmente debe ser exactamente de list tipo o es suficiente iterable?).

La ventaja de la verificación de tipo explícita es que puede detectar errores antes y dar mensajes de error más claros que la mecanografía de pato. Los requisitos exactos de un tipo de pato solo se pueden expresar con documentación externa (es de esperar que sea completa y precisa) y los errores de tipos incompatibles pueden ocurrir lejos de donde se originan.

Las sugerencias de tipos de Python están destinadas a ofrecer un compromiso en el que los tipos se pueden especificar y verificar, pero no hay ningún costo adicional durante la ejecución habitual del código.

La typing El paquete ofrece variables de tipo que se pueden usar en sugerencias de tipo para expresar los comportamientos necesarios sin requerir tipos particulares. Por ejemplo, incluye variables como Iterable y Callable para obtener sugerencias para especificar la necesidad de cualquier tipo con esos comportamientos.

Si bien las sugerencias de tipo son la forma más Pythonic de verificar los tipos, a menudo es aún más Pythonic no verificar los tipos en absoluto y confiar en la escritura de pato. Las sugerencias de tipo son relativamente nuevas y el jurado aún está deliberando sobre cuándo son la solución más Pythonic. Una comparación relativamente poco controvertida pero muy general: las sugerencias de tipo brindan una forma de documentación que se puede hacer cumplir, permiten que el código se genere más temprano y errores más fáciles de entender, puede detectar errores que el tipeo de pato no puede y se pueden verificar estáticamente (de manera inusual sentido pero todavía está fuera del tiempo de ejecución). Por otro lado, el tipado pato ha sido el método Pythonic durante mucho tiempo, no impone la sobrecarga cognitiva del tipado estático, es menos detallado y aceptará todos los tipos viables y más.

Respondido el 10 de enero de 18 a las 06:01

-1: mipy específicamente se llama a sí mismo un "verificador de tipo estático", por lo que no estoy seguro de dónde sacaste "la verificación de tipo debe realizarse en tiempo de ejecución". - Kevin

@Kevin En retrospectiva, esa fue una digresión innecesaria, pero para profundizar más, las sugerencias de tipo de Python se convierten en datos de tiempo de ejecución y mypy es un módulo de Python que usa importlib para acceder a esos datos. Si esto es una "verificación de tipo estática" es una cuestión filosófica, pero es diferente de lo que la mayoría esperaría, ya que están involucrados el intérprete de lenguaje normal y la maquinaria de importación. - Praxeolítico

Eso tampoco es cierto. Eso usos typed_ast, que a su vez es solo un clon de ast con características adicionales. ast no importa módulos; los analiza en un árbol de sintaxis abstracto. - Kevin

Aquí hay un ejemplo de por qué escribir pato es malo sin saber cuándo es peligroso. Por ejemplo: Aquí está el código Python (posiblemente omitiendo la sangría adecuada), tenga en cuenta que esta situación se puede evitar cuidando las funciones isinstance y issubclassof para asegurarse de que cuando realmente necesite un pato, no obtenga una bomba.

class Bomb:
    def __init__(self):
        ""

    def talk(self):
        self.explode()

    def explode(self):
        print "BOOM!, The bomb explodes."

class Duck:
    def __init__(self):
        ""
    def talk(self):
        print "I am a duck, I will not blow up if you ask me to talk."    

class Kid:
    kids_duck = None

    def __init__(self):
        print "Kid comes around a corner and asks you for money so he could buy a duck."

    def takeDuck(self, duck):
        self.kids_duck = duck
        print "The kid accepts the duck, and happily skips along"

    def doYourThing(self):
        print "The kid tries to get the duck to talk"
        self.kids_duck.talk()

myKid = Kid()
myBomb = Bomb()
myKid.takeDuck(myBomb)
myKid.doYourThing()

Respondido 28 Oct 13, 05:10

Incluso con la verificación de tipos, puede crear un class EvilDuck(Duck) y anular talk (). O más probablemente, class ChineseCancerDuck(Duck), con un efecto secundario desagradable que no aparece hasta años después. Sería mejor que solo supervisara a su hijo (y probara a fondo sus juguetes :) - Brett Thomas

Las bombas no hablan. No agregue métodos sin sentido y esto no sucederá. - pliegue a la derecha

@Dmitry, esta es la crítica común de Duck Typing: en.wikipedia.org/wiki/Duck_typing#Criticism ... básicamente estás diciendo que cualquier interfaz para la que el lenguaje no aplica la semántica es mala. Creo que este es más el enfoque de Java. El objetivo de la escritura pato de Python es que solo funciona cuando existe una convención comúnmente aceptada sobre lo que significan interfaces específicas. Por ejemplo, podría crear una gran cantidad de código Python anulando el __file__ atributo (comúnmente utilizado para identificar objetos similares a archivos) para significar algo más. - Dan Lenski

Todo esto se reduce al viejo chiste "Doctor, me duele cuando hago esto". ... "Entonces no hagas eso". Insatisfactorio para alguien que está acostumbrado a "si se compila, se ejecuta", pero es por eso que la obsesión por las pruebas surgió del mundo del lenguaje dinámico. - claqué

@clacke básicamente, es demasiado caro aplicar tipos en tiempo de ejecución estrictamente porque TODO debe ser un objeto (para mapear desde una cadena a cualquier tipo posible), y demasiado conveniente para no tener tipo de pato porque el tipo de pato permite técnicas de creación de prototipos realmente poderosas que superan las cosas que normalmente son muy difíciles de hacer con interfaces rígidas. Además, cualquier lenguaje estático se enfrenta a un punto en el que necesita crear tipificación pato a través de bibliotecas dinámicas, evaluación y encadenamiento, o interfaces, y estas cosas no lo hacen intrínsecamente malvado, solo muy poderoso. - Dmitry

isinstance(o, str)

Enlace a documentos

respondido 14 mar '18, 06:03

Si bien este enlace puede responder a la pregunta, es mejor incluir las partes esenciales de la respuesta aquí y proporcionar el enlace como referencia. Las respuestas de solo enlace pueden dejar de ser válidas si cambia la página enlazada. - EKons

Puede verificar el tipo de una variable usando __name__ de un tipo.

por ejemplo:

>>> a = [1,2,3,4]  
>>> b = 1  
>>> type(a).__name__
'list'
>>> type(a).__name__ == 'list'
True
>>> type(b).__name__ == 'list'
False
>>> type(b).__name__
'int'

Respondido 18 Jul 19, 18:07

Gracias, este es el código secreto que quería cuando lo mostraba como comentario para el usuario. Me tomó demasiado tiempo encontrar esto ... - Aarón D. Marasco

Creo que lo bueno de usar un lenguaje dinámico como Python es que realmente no debería tener que verificar algo así.

Simplemente llamaría a los métodos requeridos en su objeto y capturaría un AttributeError. Más adelante, esto le permitirá llamar a sus métodos con otros objetos (aparentemente no relacionados) para realizar diferentes tareas, como burlarse de un objeto para probarlo.

Lo he usado mucho cuando obtengo datos de la web con urllib2.urlopen() que devuelve un archivo como objeto. Esto, a su vez, se puede pasar a casi cualquier método que lea de un archivo, porque implementa el mismo read() método como un archivo real.

Pero estoy seguro de que hay un momento y un lugar para usar isinstance(), de lo contrario probablemente no estaría allí :)

respondido 11 nov., 17:13

Un buen ejemplo de cuando tu debe: utilícelo si está analizando un objeto json dinámico. No sabe de antemano si un campo es una cadena o un diccionario. - Gris

Para validaciones de tipo más complejas, me gusta protector de tipoEl enfoque de validación basado en anotaciones de sugerencias de tipo Python:

from typeguard import check_type
from typing import List

try:
    check_type('mylist', [1, 2], List[int])
except TypeError as e:
    print(e)

Puede realizar validaciones muy complejas de una manera muy limpia y legible.

check_type('foo', [1, 3.14], List[Union[int, float]])
# vs
isinstance(foo, list) and all(isinstance(a, (int, float)) for a in foo) 

Respondido 16 Feb 19, 07:02

Para Hugo:

Probablemente te refieres list más bien que array, pero eso apunta a todo el problema con la verificación de tipos: no desea saber si el objeto en cuestión es una lista, desea saber si es algún tipo de secuencia o si es un solo objeto. Intenta usarlo como una secuencia.

Digamos que desea agregar el objeto a una secuencia existente, o si es una secuencia de objetos, agréguelos todos

try:
   my_sequence.extend(o)
except TypeError:
  my_sequence.append(o)

Un truco con esto es si está trabajando con cadenas y / o secuencias de cadenas, eso es complicado, ya que una cadena a menudo se considera un solo objeto, pero también es una secuencia de caracteres. Peor que eso, ya que en realidad es una secuencia de cadenas de una sola longitud.

Por lo general, elijo diseñar mi API para que solo acepte un valor único o una secuencia, lo que facilita las cosas. No es difícil poner un [ ] alrededor de su valor único cuando lo transfiera si es necesario.

(Aunque esto puede causar errores con las cadenas, ya que parecen (son) secuencias).

respondido 11 nov., 17:13

Una forma sencilla de comprobar el tipo es compararlo con algo cuyo tipo conozca.

>>> a  = 1
>>> type(a) == type(1)
True
>>> b = 'abc'
>>> type(b) == type('')
True

contestado el 31 de mayo de 20 a las 21:05

Creo que la mejor manera es escribir bien las variables. Puede hacer esto usando la biblioteca de "mecanografía".

Ejemplo:

from typing import NewType UserId = NewType ('UserId', int) some_id = UserId (524313)`

Vea https://docs.python.org/3/library/typing.html

Respondido el 24 de diciembre de 19 a las 09:12

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.