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é dans Python 2.6 et j'ai besoin d'écrire du code qui fonctionne avec Python 2.5+
Donc if isinstance(var, Numbers.number)
n'est pas une solution.
Quelle serait la bonne solution dans ce cas?
Dans Python 2, vous pouvez utiliser le module types
:
>>> import types
>>> var = 1
>>> NumberTypes = (types.IntType, types.LongType, types.FloatType, types.ComplexType)
>>> isinstance(var, NumberTypes)
True
Notez l'utilisation d'un Tuple pour tester contre plusieurs types.
Sous le capot, IntType
n'est qu'un alias pour int
, etc.:
>>> isinstance(var, (int, long, float, complex))
True
Le type complex
nécessite que votre python a été compilé avec la prise en charge des nombres complexes; si vous voulez protéger cela, utilisez 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 directement les types:
>>> try:
... NumberTypes = (int, long, float, complex)
... except NameError:
... # No support for complex numbers compiled
... NumberTypes = (int, long, float)
...
Dans Python 3 types
n'a plus d'alias de type standard, complex
est toujours activé et il n'y a plus de long
vs int
différence, donc dans Python 3 utilisez toujours:
NumberTypes = (int, float, complex)
Enfin, vous pouvez utiliser le type de base abstrait numbers.Numbers
(nouveau dans Python 2.6) pour prendre également en charge les types numériques personnalisés qui ne le font pas dérivent directement des types ci-dessus:
>>> import numbers
>>> isinstance(var, numbers.Number)
True
Cette vérification renvoie également 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 prend en charge quatre types pour les nombres int
, float
, long
et complex
et python 3.x
prend en charge 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
Selon ce que vous utilisez dans typage du canard pourrait être une meilleure approche (c'est certainementcommunémentrecommandé ) . 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: les nombres rationnels sympy, les entiers de précision arbitraire et toute implémentation de nombres complexes.
Une alternative consiste à é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 implémentation raisonnable d'un nombre. Bien sûr, il y a un inconvénient majeur: cela fonctionnera également avec une implémentation déraisonnable de nombreux non-nombres (c'est-à-dire si l'opérateur plus est surchargé et accepte un entier).
Une autre alternative (selon la raison pour laquelle vous devez savoir si quelque chose est un nombre) est de supposer simplement que c'est un nombre, et si ce n'est pas le cas, des erreurs seront lancées par le bit du code qui nécessite un nombre.
Je ne dis pas que ces approches sont toujours meilleures (contrairement à certaines personnes ...) juste qu'elles valent la peine d'être considérées.