Comment utiliser correctement python isinstance() pour vérifier si une variable est un nombre?

j'ai trouvé un vieux code Python qui faisait quelque chose comme:

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

comme prévu, pep8 se plaint de cette recommandation d'utilisation de isinstance() .

maintenant, le problème est que le module numbers a été ajouté en python 2.6 et je dois écrire du code qui fonctionne avec Python 2.5+

Donc if isinstance(var, Numbers.number) n'est pas une solution.

Qui serait la bonne solution dans ce cas?

37
demandé sur sorin 2012-06-26 13:53:33

3 réponses

en Python 2, Vous pouvez utiliser le types module :

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

Remarque l'utilisation d'un tuple à tester différents types.

Sous le capot IntType est juste un alias pour int , etc.:

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

le type complex exige que votre python ait été compilé avec le support de nombres complexes; si vous voulez garder cette utilisation un bloc 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)
...

ou si vous utilisez les types directement:

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

en Python 3 types n'a plus d'alias de type standard, complex est toujours activé et il n'y a plus de différence long vs int , donc en Python 3 Utilisez toujours:

NumberTypes = (int, float, complex)

Last but not least, vous pouvez utiliser le numbers.Numbers abstract base type (nouveau en python 2.6) Pour aussi soutenez les types numériques personnalisés qui ne dérivent pas directement des types ci-dessus:

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

ce contrôle renvoie aussi True pour les objets decimal.Decimal() et fractions.Fraction() .

ce module fait l'hypothèse que le type complex est activé; vous obtiendrez une erreur d'importation si ce n'est pas le cas.

90
répondu Martijn Pieters 2018-08-29 09:45:01

Python 2 supporte quatre types de nombres int , float , long et complex et python 3.x supports 3: int , float et 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
16
répondu Ashwini Chaudhary 2014-04-26 17:56:30

en fonction de ce que vous utilisez dans duck typing pourrait être une meilleure approche (c'est certainement communément 151980920 "recommandé ). Le problème avec L'approche de Martijn Pieters est que vous manquerez toujours certains types de numéros de votre liste. Du haut de ma tête, votre code ne fonctionnera pas avec: des nombres rationnels sympy, des entiers de précision arbitraires et n'importe quelle implémentation de nombres complexes.

une alternative est d'écrire une fonction comme celle-ci:

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

ce code devrait fonctionner avec toute mise en œuvre raisonnable d'un nombre. Bien sûr, il y a un inconvénient majeur: cela fonctionnera aussi avec une implémentation déraisonnable de beaucoup de non-nombres (i.e. si l'opérateur plus est surchargé et accepte un entier).

une autre alternative (selon pourquoi vous avez besoin de savoir si quelque chose est un nombre) est de juste supposons que c'est un nombre, et si ce n'est pas des erreurs seront lancées par n'importe quel bit du code nécessite un nombre.

Je ne dis pas que ces approches sont toujours meilleures (contrairement à certaines personnes...) juste qu'ils sont la peine d'examiner.

2
répondu dshepherd 2017-05-23 12:25:48