Question

Existe-t-il une fonction existante dans numpy qui me dira si une valeur est un type numérique ou un tableau numpy? J'écris un code informatique qui doit gérer des nombres dans plusieurs représentations différentes (par & "Nombre &"; Je veux dire toute représentation d'une quantité numérique pouvant être manipulée à l'aide des opérateurs arithmétiques standard, + , -, *, /, **).

Quelques exemples du comportement que je recherche

>>> is_numeric(5)
True
>>> is_numeric(123.345)
True
>>> is_numeric('123.345')
False
>>> is_numeric(decimal.Decimal('123.345'))
True
>>> is_numeric(True)
False
>>> is_numeric([1, 2, 3])
False
>>> is_numeric([1, '2', 3])
False
>>> a = numpy.array([1, 2.3, 4.5, 6.7, 8.9])
>>> is_numeric(a)
True
>>> is_numeric(a[0])
True
>>> is_numeric(a[1])
True
>>> is_numeric(numpy.array([numpy.array([1]), numpy.array([2])])
True
>>> is_numeric(numpy.array(['1'])
False

Si une telle fonction n'existe pas, je sais qu'il ne devrait pas être difficile d'en écrire une, quelque chose comme

isinstance(n, (int, float, decimal.Decimal, numpy.number, numpy.ndarray))

mais y a-t-il d'autres types numériques à inclure dans la liste?

Était-ce utile?

La solution

Comme d'autres l'ont répondu, il pourrait exister d'autres types numériques que ceux que vous avez mentionnés. Une approche consisterait à vérifier explicitement les fonctionnalités souhaitées, par exemple

.
# Python 2
def is_numeric(obj):
    attrs = ['__add__', '__sub__', '__mul__', '__div__', '__pow__']
    return all(hasattr(obj, attr) for attr in attrs)

# Python 3
def is_numeric(obj):
    attrs = ['__add__', '__sub__', '__mul__', '__truediv__', '__pow__']
    return all(hasattr(obj, attr) for attr in attrs)

Ceci fonctionne pour tous vos exemples sauf le dernier, numpy.array(['1']). En effet, numpy.ndarray dispose des méthodes spéciales pour les opérations numériques mais soulève TypeError si vous essayez de les utiliser de manière inappropriée avec des tableaux de chaînes ou d'objets. Vous pouvez ajouter une vérification explicite pour ceci, comme

 ... and not (isinstance(obj, ndarray) and obj.dtype.kind in 'OSU')

Cela peut suffire.

Mais ... vous ne pouvez jamais être à 100% sûr que quelqu'un ne définira pas un autre type avec le même comportement. Un moyen plus sûr consiste à essayer de faire un calcul et de saisir le exception, quelque chose comme

def is_numeric_paranoid(obj):
    try:
        obj+obj, obj-obj, obj*obj, obj**obj, obj/obj
    except ZeroDivisionError:
        return True
    except Exception:
        return False
    else:
        return True

mais selon la fréquence à laquelle vous prévoyez d'appeler l'utiliser et avec quels arguments, cela peut ne pas être pratique (cela peut être potentiellement lent, par exemple avec de grands tableaux).

Autres conseils

En général, la manière flexible, rapide et pythonique de gérer les types inconnus consiste à effectuer certaines opérations sur ceux-ci et à capturer une exception pour les types non valides.

try:
    a = 5+'5'
except TypeError:
    print "Oops"

Il me semble que cette approche est plus facile que de mettre en place une fonction spéciale pour déterminer la certitude de type absolue.

De plus, numpy a numpy.isreal et d’autres fonctions similaires (numpy.is + Tab devrait les lister).

Ils ont tous un coin amusant, mais l'un d'entre eux pourrait être utile.

Votre is_numeric est mal défini. Voir mes commentaires à votre question.

Les autres types numériques peuvent être: long, complex, fractions.Fraction, numpy.bool_, numpy.ubyte, ...

operator.isNumberType() renvoie True pour les nombres Python et numpy.array.

Depuis Python 2.6, vous pouvez utiliser isinstance(d, numbers.Number) au lieu de obsolète <=>.

En général, il est préférable de vérifier les capacités de l'objet (par exemple, si vous pouvez lui ajouter un entier) et non son type.

isinstance(numpy.int32(4), numbers.Number) renvoie False, donc cela ne fonctionne pas tout à fait. operator.isNumberType() fonctionne sur toutes les variantes de numpy, cependant, y compris numpy.array([1]).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top