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


¿Cuál es la mejor manera de verificar si un objeto dado es de un tipo dado? ¿Qué hay de comprobar si el objeto hereda de un tipo determinado?

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


886
2017-09-30 11:00


origen


Respuestas:


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

if isinstance(o, str):

Para verificar si el tipo de o es exactamente str:

if type(o) is str:

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

if issubclass(type(o), str):

if type(o) in ([str] + str.__subclasses__()):

Ver Funciones integradas en la Biblioteca de Python Referencia para obtener información relevante.

Una nota más: en este caso, si está usando Python 2, en realidad puede querer usar:

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 separación estricta de cuerdas (str) y datos binarios (bytes)

Alternativamente, isinstance acepta una tupla de clases. Esto devolverá True si x es una instancia de cualquier subclase de cualquiera de (str, unicode):

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

1104
2017-09-30 11:07



los más La forma pitonica de verificar el tipo de un objeto es ... no verificarlo.

Dado que Python alienta Duck Typing, solo debes tratar de usar los métodos del objeto de la manera que quieras usarlos. Entonces, si su función está buscando un objeto de archivo modificable, no lo hagas comprobar que es una subclase de file, solo trata de usar su .write() ¡método!

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


142
2017-09-30 17:40



isinstance(o, str) regresará true Si 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. Regresará false Si o es de un tipo que hereda de str. ----


38
2017-09-30 11:05



Después de que la pregunta fue hecha y respondida, se agregaron sugerencias de tipo a Python. Las sugerencias de tipo en Python permiten verificar tipos, pero de una manera muy diferente a los lenguajes estáticos. Las sugerencias de tipo en Python asocian los tipos de argumentos esperados con funciones como datos accesibles en tiempo de ejecución asociados con funciones y esto permite para tipos a verificar Ejemplo de sintaxis de tipo de pista:

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 agregado no porque un error que ocurre cuando el script se ejecuta normalmente. Sin embargo, agrega atributos a la función que describe los tipos esperados que otros programas pueden consultar y usar para verificar si hay errores de tipo.

Uno de estos otros programas que se puede usar para encontrar el error de tipo 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 de su administrador de paquetes. No creo que venga con CPython pero parece tener cierto nivel de "oficialidad").

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

La ventaja de la comprobación de tipos explícita es que puede detectar los errores antes y proporcionar mensajes de error más claros que el tipado 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 tipo de Python están pensadas para ofrecer un compromiso donde los tipos pueden especificarse y verificarse, pero no hay un costo adicional durante la ejecución habitual del código.

los 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 tales como Iterable y Callable para sugerencias para especificar la necesidad de cualquier tipo con esos comportamientos.

Si bien las sugerencias de tipo son la manera más pitonica de verificar tipos, a menudo es incluso más pitónico no verificar tipos y confiar en el tipado de pato. Las sugerencias de tipo son relativamente nuevas y el jurado todavía está deliberando cuando son la solución más pitonica. Una comparación relativamente indiscutible pero muy general: las sugerencias de tipo proporcionan una forma de documentación que se puede aplicar, permite que el código genere errores más rápidos y fáciles de entender, puede detectar errores que no se pueden tipar, y se puede verificar estáticamente (de forma inusual sentido pero todavía está fuera del tiempo de ejecución). Por otro lado, la tipificación de pato ha sido la forma pitonica durante mucho tiempo, no impone la sobrecarga cognitiva del tipado estático, es menos detallada, y aceptará todos los tipos viables y algo más.


17
2018-05-06 16:12



Aquí hay un ejemplo de por qué el tipado de pato es malo sin saber cuándo es peligroso. Por ejemplo: aquí está el código de Python (posiblemente omitiendo la sangría apropiada), tenga en cuenta que esto la situación es evitable al ocuparse de la instancia y la emisión de una serie de funciones 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()

12
2018-01-25 23:54



isinstance(o, str)

Enlace a documentos


10
2017-09-30 11:01



Creo que lo mejor de usar un lenguaje dinámico como Python es que realmente no debería tener que comprobar algo como eso.

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

Lo he usado mucho al sacar datos de la web con urllib2.urlopen() que devuelve un archivo como objeto. Esto, a su vez, puede pasarse 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 lugar para usar isinstance(), de lo contrario, probablemente no estaría allí :)


5
2017-09-30 13:33