Étant donné un objet Python arbitraire, quel est le meilleur moyen de déterminer s'il s'agit d'un nombre? Ici is
est défini comme acts like a number in certain circumstances
.
Par exemple, disons que vous écrivez une classe vectorielle. Si un autre vecteur est donné, vous souhaitez trouver le produit scalaire. Si un scalaire est donné, vous souhaitez mettre à l'échelle le vecteur entier.
Vérifier si quelque chose est int
, float
, long
, bool
est ennuyeux et ne couvre pas les objets définis par l' utilisateur qui peuvent agir comme des numéros. Mais la vérification __mul__
, par exemple, n'est pas suffisante car la classe vectorielle que je viens de décrire définirait __mul__
, mais ce ne serait pas le type de nombre que je veux.
isinstance(value, Number) and type(value) != bool
Vous voulez vérifier si un objet
Si vous utilisez Python 2.5 ou une version antérieure, le seul vrai moyen est de vérifier certaines de ces «circonstances» et de voir.
Dans la version 2.6 ou supérieure, vous pouvez utiliser
isinstance
avec des nombres.Number - une classe de base abstraite (ABC) qui existe exactement à cette fin (beaucoup plus d'ABC existent dans lecollections
module pour diverses formes de collections / conteneurs, commençant à nouveau par 2.6; et, également uniquement dans ces versions, vous pouvez facilement ajouter vos propres classes de base abstraites si vous en avez besoin).Bach à 2.5 et plus tôt, "peut être ajouté
0
et n'est pas itérable" pourrait être une bonne définition dans certains cas. Mais, vous devez vraiment vous demander ce que vous demandez que ce que vous voulez considérer comme "un nombre" doit certainement pouvoir faire , et ce qu'il ne doit absolument pas être de faire - et de vérifier.Cela peut également être nécessaire dans la version 2.6 ou ultérieure, peut-être dans le but de faire vos propres enregistrements pour ajouter des types qui vous intéressent et qui ne sont pas déjà enregistrés
numbers.Numbers
- si vous souhaitez exclure certains types qui prétendent être des numéros, mais vous ne peut tout simplement pas gérer, cela prend encore plus de soin, car les ABC n'ont pas deunregister
méthode [[par exemple, vous pouvez créer votre propre ABCWeirdNum
et y enregistrer tous ces types bizarres pour vous, puis vérifiez d'abord si cela vous permetisinstance
de renflouer avant de continuer à la vérificationisinstance
de la normalenumbers.Number
pour continuer avec succès.BTW, si et quand vous avez besoin de vérifier si vous
x
pouvez ou ne pouvez pas faire quelque chose, vous devez généralement essayer quelque chose comme:La présence de en
__add__
soi ne vous dit rien d'utile, puisque par exemple toutes les séquences l'ont dans le but de concaténer avec d'autres séquences. Cette vérification équivaut à la définition «un nombre est quelque chose de tel qu'une séquence de telles choses est un argument unique valide pour la fonction intégréesum
», par exemple. Les types totalement étranges (par exemple ceux qui lèvent la "mauvaise" exception lorsqu'ils sont sommés à 0, comme, par exemple, aZeroDivisionError
ouValueError
& c) propageront l'exception, mais c'est OK, faites savoir à l'utilisateur dès que possible que ces types fous ne sont tout simplement pas acceptables en bon compagnie;-); mais, un "vecteur" qui peut être sommé en un scalaire (la bibliothèque standard de Python n'en a pas, mais bien sûr, ils sont populaires en tant qu'extensions tierces) donnerait également un résultat erroné ici, donc (par exemplecelui «non autorisé à être itérable» (par exemple, chèque quiiter(x)
soulèveTypeError
, ou pour la présence d'une méthode spéciale__iter__
- si vous êtes en version 2.5 ou antérieure et que vous avez donc besoin de vos propres vérifications).Un bref aperçu de ces complications peut être suffisant pour vous motiver à vous fier à la place à des classes de base abstraites chaque fois que c'est possible ... ;-).
la source
C'est un bon exemple où les exceptions brillent vraiment. Faites simplement ce que vous feriez avec les types numériques et attrapez
TypeError
tout le reste.Mais évidemment, cela ne vérifie que si une opération fonctionne , pas si elle a du sens ! La seule vraie solution pour cela est de ne jamais mélanger les types et de toujours savoir exactement à quelle classe de types appartiennent vos valeurs.
la source
isinstance
peut être utile dans de nombreux cas (== "check it makes sense" ainsi que l'applicabilité formelle des opérations). Changement difficile pour les personnes de longue date uniquement Python, mais une tendance subtile très importante dans la philosophie de Python selon laquelle ce serait une grave erreur d'ignorer.collections.Sequence
et les amis). Mais afaik, il n'y a pas de telles classes pour les nombres, les vecteurs ou tout autre objet mathématique.Multipliez l'objet par zéro. Tout nombre multiplié par zéro vaut zéro. Tout autre résultat signifie que l'objet n'est pas un nombre (y compris les exceptions)
L'utilisation de isNumber donnera ainsi la sortie suivante:
Production:
Il y a probablement des objets non numériques dans le monde qui définissent
__mul__
de renvoyer zéro lorsqu'ils sont multipliés par zéro, mais c'est une exception extrême. Cette solution devrait couvrir tout le code normal et sain que vous générez / encouter.Exemple de numpy.array:
production:
la source
True * 0 == 0
int
donc ma fonction dira correctement que les booléens sont des nombres.Pour reformuler votre question, vous essayez de déterminer si quelque chose est une collection ou une valeur unique. Essayer de comparer si quelque chose est un vecteur ou un nombre, c'est comparer des pommes à des oranges - je peux avoir un vecteur de chaînes ou de nombres, et je peux avoir une seule chaîne ou un seul nombre. Vous êtes intéressé par le nombre que vous en avez (1 ou plus) , pas par le type que vous avez réellement.
ma solution à ce problème est de vérifier si l'entrée est une valeur unique ou une collection en vérifiant la présence de
__len__
. Par exemple:Ou, pour l'approche de type canard, vous pouvez essayer d'itérer d'
foo
abord:En fin de compte, il est plus facile de tester si quelque chose est de type vectoriel que de tester si quelque chose est de type scalaire. Si vous avez des valeurs de type différent (c.-à-d. Chaîne, numérique, etc.), alors la logique de votre programme peut nécessiter un peu de travail - comment avez-vous fini par essayer de multiplier une chaîne par un vecteur numérique?
la source
Pour résumer / évaluer les méthodes existantes:
(Je suis venu ici par cette question )
Code
la source
float('nan'), 'nan', '123.45', '42', '42a', '0x8', '0xa'
ajoutermath.isnan
Il vaut probablement mieux faire l'inverse: vous vérifiez si c'est un vecteur. Si c'est le cas, vous effectuez un produit scalaire et dans tous les autres cas, vous tentez une multiplication scalaire.
Vérifier le vecteur est facile, car il doit être de votre type de classe de vecteur (ou hérité de celui-ci). Vous pouvez également simplement essayer d'abord de faire un produit scalaire, et si cela échoue (= ce n'était pas vraiment un vecteur), alors retombez à la multiplication scalaire.
la source
Juste pour ajouter. Peut-être pouvons-nous utiliser une combinaison de isinstance et isdigit comme suit pour déterminer si une valeur est un nombre (int, float, etc.)
si isinstance (num1, int) ou isinstance (num1, float) ou num1.isdigit ():
la source
Pour la classe vectorielle hypothétique:
Supposons que ce
v
soit un vecteur, et nous le multiplions parx
. S'il est logique de multiplier chaque composant dev
parx
, c'est probablement ce que nous voulions dire, alors essayez d'abord. Sinon, peut-être pouvons-nous dot? Sinon, c'est une erreur de type.EDIT - le code ci-dessous ne fonctionne pas, car
2*[0]==[0,0]
au lieu de lever un fichierTypeError
. Je le laisse parce qu'il a été commenté.la source
x
est un vecteur, alors[comp * x for comp in self]
donnera le produit externe dex
anv
. Ceci est un tenseur de rang 2, pas un scalaire.comp*x
sera l' échellex
parcomp
, je suppose qu'il soulèverait un TypeError. Malheureusement, il concaténerax
avec lui-même lescomp
temps. Oups.x
est un vecteur, alors il devrait avoir une__rmul__
méthode (__rmul__ = __mul__
) de sorte qu'ilcomp * x
devrait être mis à l'échellex
de la même manière quix * comp
est apparemment prévue.J'ai eu un problème similaire lors de l'implémentation d'une sorte de classe vectorielle. Une façon de vérifier un nombre est de simplement le convertir en un, c'est-à-dire en utilisant
Cela devrait rejeter les cas où x ne peut pas être converti en nombre; mais peut également rejeter d'autres types de structures de type nombre qui pourraient être valides, par exemple des nombres complexes.
la source
Si vous souhaitez appeler différentes méthodes en fonction du ou des types d'argument, regardez dans
multipledispatch
.Malheureusement, (à ma connaissance) nous ne pouvons pas écrire
@dispatch(Vector)
car nous sommes encore en train de définir le typeVector
, donc ce nom de type n'est pas encore défini. Au lieu de cela, j'utilise le type de baselist
, qui vous permet même de trouver le produit scalaire de aVector
et alist
.la source
Voie courte et simple:
Production :
Si l'objet est une chaîne, 'False' sera renvoyé:
Production :
la source
Vous avez un élément de données, dites
rec_day
que lorsqu'il est écrit dans un fichier sera un fichierfloat
. Mais pendant le traitement du programme, il peut être soitfloat
,int
soit destr
type (lestr
est utilisé lors de l'initialisation d'un nouvel enregistrement et contient une valeur d'indicateur factice).Vous pouvez ensuite vérifier si vous avez un numéro avec ce
J'ai structuré un programme python de cette façon et je viens de mettre un `` correctif de maintenance '' en l'utilisant comme une vérification numérique. Est-ce la voie pythonique? Probablement pas depuis que je programmais en COBOL.
la source
Vous pouvez utiliser la fonction isdigit ().
la source