2012-06-26 9 views
32

me encontré con un viejo código Python que estaba haciendo algo como:¿Cómo usar python's isinstance() para comprobar si una variable es un número?

if type(var) is type(1): 
    ... 

Como era de esperar, pep8 se queja de este uso de recomendar isinstance().

Ahora, el problema es que el módulo numbers se añadió en Python 2.6 y tengo que escribir código que funciona con Python 2.5 +

Así if isinstance(var, Numbers.number) no es una solución.

¿Cuál sería la solución adecuada en este caso?

+0

Si está dispuesto a usar numpy, 'numpy.isfinite' debería hacer el truco. –

Respuesta

83

Puede utilizar el types module:

>>> import types 
>>> var = 1 
>>> NumberTypes = (types.IntType, types.LongType, types.FloatType, types.ComplexType) 
>>> isinstance(var, NumberTypes) 
True 

Nota del uso de una tupla para probar contra varios tipos.

Bajo el capó, IntType es sólo un alias para int, etc .:

>>> isinstance(var, (int, long, float, complex)) 
True 

El tipo complex requiere que su pitón fue compilado con soporte para los números complejos; si desea guardar para este uso un bloque try/except:

>>> try: 
...  NumberTypes = (types.IntType, types.LongType, types.FloatType, types.ComplexType) 
... except AttributeError: 
...  # No support for complex numbers compiled 
...  NumberTypes = (types.IntType, types.LongType, types.FloatType) 
... 

o si sólo tiene que utilizar los tipos directamente:

>>> try: 
...  NumberTypes = (int, long, float, complex) 
... except NameError: 
...  # No support for complex numbers compiled 
...  NumberTypes = (int, long, float) 
... 

Por último, pero no menos importante, se puede utilizar el numbers.Numbers abstract base type (nuevo en Python 2.6) para apoyar también los tipos numéricos personalizados que no derivan directamente de los tipos anteriores:

>>> import numbers 
>>> isinstance(var, numbers.Number) 
True 

Este módulo hace que el supuesto de que el tipo complex está activado; obtendrá un error de importación si no es así.

+3

'isinstance()' puede tomar una tupla de objetos?!? Woah, amigo ... –

+0

@Def_Os: sí, y esta ha sido una característica desde Python 2.2. –

+0

Realmente deberías poner eso en la parte superior de tu respuesta. –

13

Python 2 soporta cuatro tipos de números int, float, long y complex y python 3.x soportes 3: int, float y complex

>>> num = 10 
>>> if isinstance(num, (int, float, long, complex)): #use tuple if checking against multiple types 
     print('yes it is a number') 

yes it is a number 
>>> isinstance(num, float) 
False 
>>> isinstance(num, int) 
True 
>>> a = complex(1, 2) 
>>> isinstance(a, complex) 
True 
2

Dependiendo de lo que usted está usando esto en duck typing podría ser un mejor enfoque (es certainlycommonlyrecommended). El problema con el enfoque de Martijn Pieters es que siempre perderá algunos tipos de números de su lista. En la parte superior de mi cabeza, tu código no funcionará con: números racionales sympy, enteros de precisión arbitrarios y cualquier implementación de números complejos.

Una alternativa es escribir una función como esta:

def is_number(thing): 
    try: 
     thing + 1 
     return True 
    except TypeError: 
     return False 

Este código debería funcionar con cualquier aplicación razonable de un número. Por supuesto, hay un inconveniente importante: también funcionará con una implementación irrazonable de muchos no-números (es decir, si el operador más está sobrecargado y acepta un número entero).

Otra alternativa (dependiendo de por qué necesita saber si algo es un número) es simplemente asumir que es un número, y si no lo es, se arrojará un error por cualquier parte del código que requiera un número.

No digo que estos enfoques sean siempre mejores (a diferencia de algunas personas ...) simplemente que valen la pena considerarlos.

Cuestiones relacionadas