validar tipo español dato python typing dynamic-typing

tipo - isinstance python español



¿Cómo puedo verificar las variables en Python? (8)

Tengo una función de Python que toma un argumento numérico que debe ser un número entero para que se comporte correctamente. ¿Cuál es la forma preferida de verificar esto en Python?

Mi primera reacción es hacer algo como esto:

def isInteger(n): return int(n) == n

Pero no puedo dejar de pensar que esto es 1) caro 2) feo y 3) sujeto a las misericordias de la máquina épsilon.

¿Proporciona Python algún medio nativo de variables de verificación de tipo? ¿O esto se considera una violación del diseño de tipado dinámico del idioma?

EDITAR: ya que varias personas han preguntado: la aplicación en cuestión funciona con prefijos IPv4, obteniendo datos de archivos de texto plano. Si cualquier entrada se analiza en un flotante, ese registro se debe ver como mal formado e ignorado.


No escriba cheque. El objetivo de la mecanografía de patos es que no deberías tener que hacerlo. Por ejemplo, ¿qué pasa si alguien hizo algo como esto?

class MyInt(int): # ... extra stuff ...


if type(n) is int

Esto comprueba si n es un int Python, y solo un int. No aceptará subclases de int .

La comprobación de tipos, sin embargo, no se ajusta a la "forma de Python". Será mejor que uses n como int, y si arroja una excepción, tómalo y actúa sobre él.


Programar en Python y realizar la verificación de tipo como lo haría en otros idiomas parece elegir un destornillador para clavar un clavo. Es más elegante usar las funciones de manejo de excepciones de Python.

Desde una línea de comando interactiva, puede ejecutar una declaración como:

int(''sometext'')

Eso generará un error - ipython me dice:

<type ''exceptions.ValueError''>: invalid literal for int() with base 10: ''sometext''

Ahora puedes escribir un código como:

try: int(myvar) + 50 except ValueError: print "Not a number"

Eso se puede personalizar para realizar cualquier operación que se requiera Y para detectar los errores que se esperan. Parece un poco intrincado, pero se ajusta a la sintaxis y modismos de Python y da como resultado un código muy legible (una vez que te acostumbras a hablar Python).


isinstance(n, int)

Si necesita saber si es definitivamente una int real y no una subclase de int (generalmente no debería necesitar hacer esto):

type(n) is int

esta:

return int(n) == n

no es una buena idea, ya que las comparaciones de tipo cruzado pueden ser ciertas, notablemente int(3.0)==3.0


qué tal si:

def ip(string): subs = string.split(''.'') if len(subs) != 4: raise ValueError("incorrect input") out = tuple(int(v) for v in subs if 0 <= int(v) <= 255) if len(out) != 4: raise ValueError("incorrect input") return out

por supuesto existe la función estándar de instancia (3, int) ...


Sí, como dijo Evan, no marques el cheque. Intenta usar el valor:

def myintfunction(value): """ Please pass an integer """ return 2 + value

Eso no tiene un control de tipo. ¡Es mucho mejor! Veamos qué sucede cuando lo intento:

>>> myintfunction(5) 7

Eso funciona, porque es un número entero. Hm. Vamos a probar algo de texto.

>>> myintfunction(''text'') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in myintfunction TypeError: unsupported operand type(s) for +: ''int'' and ''str''

Muestra un error, TypeError, que es lo que debería hacer de todos modos. Si la persona que llama quiere captar eso, es posible.

¿Qué harías si hicieras una prueba de tipo? Muestra un error ¿no? Por lo tanto, no es necesario que haga una comprobación de tipo porque el error ya se muestra automáticamente.

Además, dado que no realizó la verificación de tipo, tiene su función trabajando con otros tipos:

Flotadores:

>>> print myintfunction(2.2) 4.2

Números complejos:

>>> print myintfunction(5j) (2+5j)

Decimales:

>>> import decimal >>> myintfunction(decimal.Decimal(''15'')) Decimal("17")

¡Incluso objetos completamente arbitrarios que pueden agregar números!

>>> class MyAdderClass(object): ... def __radd__(self, value): ... print ''got some value: '', value ... return 25 ... >>> m = MyAdderClass() >>> print myintfunction(m) got some value: 2 25

Entonces, claramente no obtienes nada al verificar el tipo. Y pierdes mucho.

ACTUALIZAR:

Ya que ha editado la pregunta, ahora está claro que su aplicación llama a alguna rutina en sentido ascendente que solo tiene sentido con las entradas.

Siendo ese el caso, sigo pensando que deberías pasar el parámetro como se recibió a la función ascendente. La función upstream se ocupará de ello correctamente, por ejemplo, generar un error si es necesario. Dudo mucho que su función que se ocupa de IP se comportará de manera extraña si le pasa un flotador. Si nos puede dar el nombre de la biblioteca, podemos verificarlo por usted.

Pero ... Si la función ascendente se comportará de forma incorrecta y matará a algunos niños si pasas un flotador (aún lo dudo), simplemente llama a int() en él:

def myintfunction(value): """ Please pass an integer """ return upstreamfunction(int(value))

Todavía no está realizando la verificación de tipo, por lo que obtiene la mayoría de los beneficios de no realizar la verificación de tipo.

Si incluso después de todo eso, realmente desea escribir verificación, a pesar de que reduce la legibilidad y el rendimiento de su aplicación sin ningún beneficio, use una assert para hacerlo.

assert isinstance(...) assert type() is xxxx

De esa forma podemos desactivar assert y eliminar esta característica <sarcasm> </sarcasm> del programa llamándolo como

python -OO program.py


Python ahora admite el tipado gradual a través del módulo de tipeo y mypy . El módulo de typing es una parte del stdlib de Python 3.5 y se puede descargar de PyPi si necesita backports para Python 2 o una versión previa de Python 3. Puede instalar mypy ejecutando pip install mypy desde la línea de comandos.

En resumen, si quiere verificar que alguna función toma un int, un float y devuelve una cadena, anotaría su función de la siguiente manera:

def foo(param1: int, param2: float) -> str: return "testing {0} {1}".format(param1, param2)

Si su archivo se llamó test.py , entonces puede tipear una vez que haya instalado mypy ejecutando mypy test.py desde la línea de comando.

Si está utilizando una versión anterior de Python sin soporte para anotaciones de funciones, puede usar los comentarios de tipo para lograr el mismo efecto:

def foo(param1, param2): # type: (int, float) -> str return "testing {0} {1}".format(param1, param2)

Utiliza el mismo comando mypy test.py para archivos Python 3 y mypy --py2 test.py para archivos Python 2.

Las anotaciones de tipo son ignoradas por completo por el intérprete de Python en tiempo de ejecución, por lo que imponen una sobrecarga mínima o nula: el flujo de trabajo habitual es trabajar en su código y ejecutar mypy periódicamente para detectar errores y errores. Algunos IDEs, como PyCharm, comprenderán sugerencias de tipo y pueden alertarlo sobre problemas y escribir errores en su código mientras está editando directamente.

Si, por algún motivo, necesita que se comprueben los tipos en tiempo de ejecución (quizás deba validar una gran cantidad de datos?), Debe seguir los consejos enumerados en las otras respuestas, por ejemplo, use isinstance , issubclass y similares. También hay algunas bibliotecas, como Forzar, que intentan realizar la comprobación de tipo (respetando las anotaciones de tipo) en tiempo de ejecución, aunque no estoy seguro de cuán listos para producción están al momento de escribir.

Para obtener más información y detalles, consulte el sitio web mypy , las preguntas frecuentes mypy y PEP 484 .


Estaría tentado de algo como:

def check_and_convert(x): x = int(x) assert 0 <= x <= 255, "must be between 0 and 255 (inclusive)" return x class IPv4(object): """IPv4 CIDR prefixes is A.B.C.D/E where A-D are integers in the range 0-255, and E is an int in the range 0-32.""" def __init__(self, a, b, c, d, e=0): self.a = check_and_convert(a) self.b = check_and_convert(a) self.c = check_and_convert(a) self.d = check_and_convert(a) assert 0 <= x <= 32, "must be between 0 and 32 (inclusive)" self.e = int(e)

De esa forma, cuando lo esté usando, cualquier cosa puede pasarse, pero solo almacena un número entero válido.