web-dev-qa-db-fra.com

python: comment identifier si une variable est un tableau ou un scalaire

J'ai une fonction qui prend l'argument NBins. Je souhaite appeler cette fonction avec un 50 scalaire ou un [0, 10, 20, 30] de tableau. Comment puis-je identifier dans la fonction, quelle est la longueur de NBins? ou dit différemment, si c'est un scalaire ou un vecteur? 

J'ai essayé ceci:

>>> N=[2,3,5]
>>> P = 5
>>> len(N)
3
>>> len(P)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'int' has no len()
>>> 

Comme vous le voyez, je ne peux pas appliquer len à P, car ce n'est pas un tableau .... Y at-il quelque chose comme isarray ou isscalar en python?

merci

222
otmezger
>>> isinstance([0, 10, 20, 30], list)
True
>>> isinstance(50, list)
False

Pour prendre en charge tout type de séquence, cochez collections.Sequence au lieu de list.

note : isinstance prend également en charge un nuplet de classes, cochez la case type(x) in (..., ...) qui devrait être évitée et inutile.

Vous pouvez également vouloir vérifier not isinstance(x, (str, unicode))

296
jamylak

Les réponses précédentes supposent que le tableau est une liste standard Python. En tant que personne qui utilise numpy souvent, je recommanderais un test très Pythonic de

if hasattr(N, "__len__")
95
jpaddison3

En combinant les réponses de @jamylak et de @ jpaddison3, si vous devez être robuste contre les tableaux numpy comme entrée et les gérer de la même manière que des listes, vous devez utiliser

import numpy as np
isinstance(P, (list, Tuple, np.ndarray))

Ceci est robuste contre les sous-classes de tableaux list, tuple et numpy.

Et si vous voulez également être robuste contre toutes les autres sous-classes de séquence (pas seulement list et tuple), utilisez

import collections
import numpy as np
isinstance(P, (collections.Sequence, np.ndarray))

Pourquoi devriez-vous faire les choses de cette façon avec isinstance et ne pas comparer type(P) avec une valeur cible? Voici un exemple où nous fabriquons et étudions le comportement de NewList, une sous-classe triviale de la liste.

>>> class NewList(list):
...     isThisAList = '???'
... 
>>> x = NewList([0,1])
>>> y = list([0,1])
>>> print x
[0, 1]
>>> print y
[0, 1]
>>> x==y
True
>>> type(x)
<class '__main__.NewList'>
>>> type(x) is list
False
>>> type(y) is list
True
>>> type(x).__name__
'NewList'
>>> isinstance(x, list)
True

Bien que x et y soient égaux, leur traitement par type entraînerait un comportement différent. Cependant, étant donné que x est une instance d'une sous-classe de list, l'utilisation de isinstance(x,list) donne le comportement souhaité et traite x et y de la même manière.

33
scottclowe

Existe-t-il un équivalent à isscalar () dans numpy? Oui. 

>>> np.isscalar(3.1)
True
>>> np.isscalar([3.1])
False
>>> np.isscalar(False)
True
23
jmhl

Bien que l'approche de @ jamylak soit la meilleure, voici une approche alternative

>>> N=[2,3,5]
>>> P = 5
>>> type(P) in (Tuple, list)
False
>>> type(N) in (Tuple, list)
True
15
Sukrit Kalra

Utilisez simplement size au lieu de len!

>>> from numpy import size
>>> N = [2, 3, 5]
>>> size(N)
3
>>> N = array([2, 3, 5])
>>> size(N)
3
>>> P = 5
>>> size(P)
1
3
Mathieu Villion

Une autre approche alternative (utilisation de la classe nom propriété):

N = [2,3,5]
P = 5

type(N).__== 'list'
True

type(P).__== 'int'
True

type(N).__in ('list', 'Tuple')
True

Pas besoin d'importer quoi que ce soit.

3
Marek

Vous pouvez vérifier le type de données de la variable.

N = [2,3,5]
P = 5
type(P)

Il vous donnera mis en tant que type de données de P.

<type 'int'>

Pour que vous puissiez différencier qu'il s'agit d'un entier ou d'un tableau.

2
unnati patil
>>> N=[2,3,5]
>>> P = 5
>>> type(P)==type(0)
True
>>> type([1,2])==type(N)
True
>>> type(P)==type([1,2])
False
2
simple_human

Je suis surpris qu'une question aussi fondamentale ne semble pas avoir de réponse immédiate en python ..__ Il me semble que presque toutes les réponses proposées utilisent un type de type ils semblent limités à un cas spécifique (ils échouent avec des types numériques différents ou des objets génériques itératifs qui ne sont ni des uplets ni des listes) 

Pour moi, ce qui fonctionne mieux, c'est importer numpy et utiliser array.size, par exemple: 

>>> a=1
>>> np.array(a)
Out[1]: array(1)

>>> np.array(a).size
Out[2]: 1

>>> np.array([1,2]).size
Out[3]: 2

>>> np.array('125')
Out[4]: 1

Notez aussi:

>>> len(np.array([1,2]))

Out[5]: 2

mais:

>>> len(np.array(a))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-40-f5055b93f729> in <module>()
----> 1 len(np.array(a))

TypeError: len() of unsized object
1
Vincenzooo

preds_test [0] est de forme (128,128,1) Vérifions son type de données en utilisant isinstance (), fonction isinstance prend 2 arguments. Le premier argument est la donnée Le deuxième argument est le type de données isinstance (preds_test [0], np.ndarray) donne la sortie en tant que True. Cela signifie que preds_test [0] est un tableau.

0
Sumanth Meenan

Voici la meilleure approche que j'ai trouvée: Vérifiez l'existence de __len__ et __getitem__

Vous pouvez demander pourquoi? Les raisons incluent:

  1. Ceci détecte plusieurs objets populaires qui sont en fait des tableaux, y compris la liste native de Python et Tuple, le ndarray de NumPy et le tensor de PyTorch. 
  2. Une autre méthode populaire, isinstance(obj, abc.Sequence), échoue sur certains objets, notamment le tensionneur de PyTorch, car ils ne mettent pas en œuvre __contains__.
  3. Utiliser collections.abc est bien préférable, mais malheureusement, rien dans le fichier collections.abc de Python ne vérifie que __len__ et __getitem__.

Alors sans plus tarder:

def is_array_like(obj, string_is_array=False, Tuple_is_array=True):
    result = hasattr(obj, "__len__") and hasattr(obj, '__getitem__') 
    if result and not string_is_array and isinstance(obj, (str, abc.ByteString)):
        result = False
    if result and not Tuple_is_array and isinstance(obj, Tuple):
        result = False
    return result

Notez que j'ai ajouté des paramètres par défaut car la plupart du temps, vous souhaiterez peut-être considérer les chaînes comme des valeurs, et non des tableaux. De même pour les tuples.

0
Shital Shah