webentwicklung-frage-antwort-db.com.de

python: Wie erkennt man, ob eine Variable ein Array oder ein Skalar ist?

Ich habe eine Funktion, die das Argument NBins übernimmt. Ich möchte diese Funktion mit einem Skalar 50 oder einem Array [0, 10, 20, 30] aufrufen. Wie kann ich innerhalb der Funktion feststellen, wie lang NBins ist? oder anders gesagt, wenn es ein Skalar oder ein Vektor ist? 

Ich habe das versucht:

>>> 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()
>>> 

Wie Sie sehen, kann ich len nicht auf P anwenden, da es kein Array ist .... Gibt es in Python etwas wie isarray oder isscalar?

vielen Dank

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

Um einen beliebigen Sequenztyp zu unterstützen, aktivieren Sie collections.Sequence anstelle von list.

note : isinstance unterstützt auch ein Tuple von Klassen. Die Überprüfung von type(x) in (..., ...) sollte vermieden werden und ist nicht erforderlich.

Vielleicht möchten Sie auch not isinstance(x, (str, unicode)) prüfen

296
jamylak

Bei früheren Antworten wird davon ausgegangen, dass das Array eine Python-Standardliste ist. Als jemand, der häufig mit Numpy arbeitet, würde ich einen sehr pythonischen Test empfehlen:

if hasattr(N, "__len__")
95
jpaddison3

Wenn Sie die Antworten von @jamylak und @ jpaddison3 miteinander kombinieren, sollten Sie die Verwendung von numpy-Arrays als Eingabe benötigen und sie wie Listen behandeln, die Sie verwenden sollten

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

Dies ist robust gegenüber Unterklassen von List-, Tuple- und Numpy-Arrays.

Und wenn Sie auch gegenüber allen anderen Unterklassen der Sequenz (nicht nur Liste und Tupel) robust sein wollen, verwenden Sie

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

Warum sollten Sie dies mit isinstance tun und type(P) nicht mit einem Zielwert vergleichen? Hier ist ein Beispiel, wo wir das Verhalten von NewList, einer trivialen Unterklasse von list, erstellen und studieren.

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

Obwohl x und y als gleich betrachtet werden, führt die Behandlung mit type zu unterschiedlichem Verhalten. Da jedoch x eine Instanz einer Unterklasse von list ist, ergibt die Verwendung von isinstance(x,list) das gewünschte Verhalten und behandelt x und y auf dieselbe Weise.

33
scottclowe

Gibt es ein Äquivalent zu isscalar () in numpy? Ja. 

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

@ Jamylak ist zwar der bessere Ansatz, aber hier ist ein alternativer Ansatz

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

Verwenden Sie einfach size anstelle von 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

Ein anderer alternativer Ansatz (Verwendung von Klasse Name Eigenschaft):

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

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

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

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

Sie müssen nichts importieren.

3
Marek

Sie können den Datentyp der Variablen überprüfen.

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

Es wird Ihnen als Datentyp P übergeben.

<type 'int'>

Damit Sie unterscheiden können, dass es sich um eine Ganzzahl oder ein Array handelt.

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

Ich bin erstaunt, dass eine solche grundlegende Frage in Python keine unmittelbare Antwort zu haben scheint ... _ Es scheint mir, dass fast alle vorgeschlagenen Antworten eine Art von Prüfung verwenden, die normalerweise nicht in Python empfohlen wird Sie scheinen auf einen bestimmten Fall beschränkt zu sein (sie versagen mit verschiedenen numerischen Typen oder generischen iterierbaren Objekten, die keine Tupel oder Listen sind). 

Was für mich besser funktioniert, ist das Importieren von numpy und das Verwenden von array.size, zum Beispiel: 

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

Beachten Sie auch:

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

Out[5]: 2

aber:

>>> 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] hat die Form (128,128,1) Lässt den Datentyp mit der Funktion isinstance () überprüfen. isinstance benötigt 2 Argumente. Das erste Argument ist data. Das zweite Argument ist der Datentyp isinstance. (Preds_test [0], np.ndarray) gibt Output als True aus. Dies bedeutet, dass preds_test [0] ein Array ist.

0
Sumanth Meenan

Hier ist der beste Ansatz, den ich gefunden habe: Überprüfen Sie die Existenz von __len__ und __getitem__

Sie fragen vielleicht warum? Die Gründe umfassen:

  1. Dies erkennt mehrere beliebte Objekte, bei denen es sich um Arrays handelt, darunter die native Liste von Python und Tuple, NumPys Narray und PyTorch's Tensor. 
  2. Eine andere beliebte Methode isinstance(obj, abc.Sequence) schlägt bei einigen Objekten, einschließlich des Tensors von PyTorch, fehl, da sie __contains__ nicht implementieren.
  3. Die Verwendung von Collections.abc ist viel vorzuziehen, aber leider enthält Python Collections.abc nichts, was nur nach __len__ und __getitem__ sucht.

Also ohne weiteres:

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

Beachten Sie, dass ich Standardparameter hinzugefügt habe, da Sie Strings meistens als Werte und nicht als Arrays betrachten möchten. Ähnlich für Tupel.

0
Shital Shah