Python comprueba si la instancia es de algún tipo en la lista.

86

¿Cómo lo hago pitónicamente?

var = 7.0
var_is_good = isinstance(var, classinfo1) or isinstance(var, classinfo2) or isinstance(var, classinfo3) or ... or  isinstance(var, classinfoN)

Parece una tontería no puedo simplemente pasar una lista de información de clase:

var_is_good = isinstanceofany( var, [classinfo1, classinfo2, ... , classinfoN] )

Entonces, ¿cuál es la isinstanceofanyfunción?

D Adams
fuente
Si suma como un número, resta como un número, multiplica como un número ... ¿por qué necesitas saber si es un número? Consulte la escritura de pato para obtener más detalles.
Makoto
Mi caso de uso particular es tener una función que devuelve una (función que devuelve (ya sea una numberO devuelve una expresión sympy)). Quiero comprobar que la función que generé hace lo que se supone que debe hacer cuando la paso a otras funciones.
D Adams
¿Por qué su función no devuelve algo homogéneo? Eso es lo que huele aquí; puede ser rápido y relajado con la escritura de pato, pero debe ser consistente en lo que devuelve.
Makoto
Supongo que siempre podría devolver una expresión simpática que a veces se evalúa como un número y, a veces, tiene variables dentro.
D Adams
Eso es lo que estoy pensando que quieres hacer aquí; en lugar de devolver varios tipos diferentes, devuelva el único tipo y, si es necesario, redúzcalo a un número.
Makoto

Respuestas:

190

isinstance()toma una tupla de clases para el segundo argumento. Devolverá verdadero si el primer argumento es una instancia de cualquiera de los tipos en esa secuencia:

isinstance(var, (classinfo1, classinfo2, classinfo3))

En otras palabras, isinstance() ya ofrece esta funcionalidad, lista para usar.

De la isinstance()documentación :

Si classinfo no es un objeto de clase ni un objeto de tipo, puede ser una tupla de objetos de clase o de tipo, o puede contener de forma recursiva otras tuplas similares (no se aceptan otros tipos de secuencia).

Énfasis mío; tenga en cuenta la naturaleza recursiva; (classinfo1, (classinfo2, classinfo3))también es una opción válida.

Martijn Pieters
fuente
¡Útil, gracias!
Yaakov Bressler
11

Ya estabas bastante cerca del título de tu pregunta. Podrías usar anyy una lista:

var = 7.0
var_is_good = any([isinstance(var, classinfo1),
                   isinstance(var, classinfo2),
                   isinstance(var, classinfo3), ...
                   isinstance(var, classinfoN)])

Pero mirando en los documentos de isinstancerevela:

Devuelve verdadero si el argumento del objeto es una instancia del argumento classinfo, o de una subclase (directa, indirecta o virtual) del mismo. Si el objeto no es un objeto del tipo dado, la función siempre devuelve falso. Si classinfo no es una clase (objeto de tipo), puede ser una tupla de objetos de tipo , o puede contener recursivamente otras tuplas similares (no se aceptan otros tipos de secuencia). Si classinfo no es un tipo o tupla de tipos y tales tuplas, se genera una excepción TypeError.

Esto significa que la mejor manera de hacerlo es

var = 7.0
var_is_good = isinstance(var, (classinfo1,
                               classinfo2,
                               classinfo3,
                               ...,
                               classinfoN))
Martín Thoma
fuente
2
Repetir isinstancecon solo el classinfocambio no me parece muy Pythonic.
Makoto
1
Prueba var.__class__. ¿Es eso lo que quieres? @Makoto: Estoy de acuerdo. ¡No es Pythonic en absoluto!
flamenco
@Makoto Sí. Pero eso era algo que D Adams probablemente podría haber encontrado fácilmente buscando en los documentos "cualquier". He ampliado mi respuesta a la mejor versión ... pero obviamente Martijn Pieters fue más rápido ... una vez más.
Martin Thoma
3
any()con una lista es ... inútil. Use una expresión generadora si debe usar any(), entonces al menos obtendrá el beneficio de la salida anticipada.
Martijn Pieters
Creo que la isinstancetupla with es el camino a seguir. Solo quería mencionar la solución, anyya que parecía ser lo que estaba pidiendo en el título.
Martin Thoma
4

Esto resolverá tu problema:

valid_instance_types = <tuple of types you want to allow>
var_is_good = isinstance(var, valid_instance_types)

Según la documentación, hay muchas formas de pasar valores de tipos isinstance.

También puede parecer voluptuoso si está tratando de hacer una validación más complicada de la cual esto es solo una parte.

Nathaniel Ford
fuente
isinstance () ya ofrece esta funcionalidad, pase una tupla con todos los tipos necesarios para verificar como segundo argumento
RFV
@ RFV5s Sí ... eso es lo que muestra el ejemplo que proporcioné aquí. ¿Cuál es tu objeción?
Nathaniel Ford
1

Por lo general, no debería usarlo isinstance, pero lo que desea hacer se puede lograr con la función incorporada any () .

var_is_good = any(isinstance(var, t) for t in [type1, type2, type3])
Chad S.
fuente
7
Esto es una exageración; isinstance()ofrece la funcionalidad lista para usar sin usar any().
Martijn Pieters
@MartijnPieters No me di cuenta de que isinstance puede tomar varios tipos, pero siento que la respuesta sigue siendo buena porque la pregunta se puede tomar de manera más amplia como "¿Cómo verifico si alguno de los valores de retorno de una función en particular con diferentes parámetros es cierto "
Chad S.
Si debe usar o no isinstance()es irrelevante.
RFV
@ChadS. Me gustaría preguntarte por qué crees que no debería usarlo isinstance(). Gracias.
Salida
Porque Python evita la verificación de tipos. Es mucho código adicional (y ciclos de CPU) para poco beneficio. Se prefiere la tipificación de pato.
Chad S.