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?
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.
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
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.