398 Stimmen

Python: wie man erkennt, ob eine Variable ein Array oder ein Skalar ist

Ich habe eine Funktion, die das Argument NBins annimmt. Ich möchte diese Funktion mit einem Skalar 50 oder einem Array [0, 10, 20, 30] aufrufen. Wie kann ich innerhalb der Funktion identifizieren, wie lang NBins ist? Oder anders gesagt, ob es sich um einen Skalar oder einen Vektor handelt?

Ich habe es so versucht:

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

Wie du siehst, kann ich len nicht auf P anwenden, da es sich nicht um ein Array handelt... Gibt es in Python etwas wie isarray oder isscalar?

Danke

538voto

jamylak Punkte 119693
>>> import collections.abc
>>> isinstance([0, 10, 20, 30], collections.abc.Sequence)
True
>>> isinstance(50, collections.abc.Sequence)
False

Hinweis: isinstance unterstützt auch ein Tupel von Klassen, Überprüfen Sie type(x) in (..., ...) sollte vermieden werden und ist unnötig.

Sie sollten auch überprüfen not isinstance(x, (str, unicode))

Wie von @2080 und auch hier angemerkt wurde, funktioniert dies nicht für numpy Arrays. z. B.

>>> import collections.abc
>>> import numpy as np
>>> isinstance((1, 2, 3), collections.abc.Sequence)
True
>>> isinstance(np.array([1, 2, 3]), collections.abc.Sequence)
False

In diesem Fall können Sie die Antwort von @jpaddison3 ausprobieren:

>>> hasattr(np.array([1, 2, 3]), "__len__")
True
>>> hasattr([1, 2, 3], "__len__")
True
>>> hasattr((1, 2, 3), "__len__")
True

Wie jedoch hier angemerkt wird, ist auch dies nicht perfekt und wird fälschlicherweise (zumindest nach meiner Meinung) Wörterbücher als Sequenzen klassifizieren, während isinstance mit der Klasse collections.abc.Sequence korrekt klassifiziert:

>>> hasattr({"a": 1}, "__len__")
True
>>> from numpy.distutils.misc_util import is_sequence
>>> is_sequence({"a": 1})
True
>>> isinstance({"a": 1}, collections.abc.Sequence)
False

Sie könnten Ihre Lösung anpassen und etwas ähnliches tun, fügen Sie je nach Bedarf weitere Typen zu isinstance hinzu:

>>> isinstance(np.array([1, 2, 3]), (collections.abc.Sequence, np.ndarray))
True
>>> isinstance([1, 2, 3], (collections.abc.Sequence, np.ndarray))
True

167voto

jpaddison3 Punkte 1896

Frühere Antworten gehen davon aus, dass das Array eine Python-Standardliste ist. Als jemand, der oft numpy verwendet, würde ich einen sehr pythonischen Test empfehlen:

if hasattr(N, "__len__")

77voto

scottclowe Punkte 1507

Die Antworten von @jamylak und @jpaddison3 kombinierend, sollten Sie, wenn Sie gegen numpy-Arrays als Eingabe robust sein müssen und sie genauso wie Listen behandeln möchten, verwenden Sie

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

Dies ist robust gegen Unterklassen von Listen, Tupeln und numpy-Arrays.

Und wenn Sie auch gegen alle anderen Unterklassen von Sequenzen robust sein möchten (nicht nur Listen und Tupel), verwenden Sie

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

Warum sollten Sie das auf diese Weise mit isinstance machen und nicht type(P) mit einem Zielfwert vergleichen? Hier ist ein Beispiel, wie wir das Verhalten von NewList, einer trivialen Unterklasse von Listen, erstellen und untersuchen.

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

>>> type(x) is list
False
>>> type(y) is list
True
>>> type(x).__name__
'NewList'
>>> isinstance(x, list)
True

Trotz des Vergleichs von x und y als gleich würde die Behandlung durch type zu unterschiedlichem Verhalten führen. 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 die gleiche Weise.

63voto

jmhl Punkte 1557

Gibt es einen Äquivalenten zu isscalar() in numpy? Ja.

>>> np.isscalar(3.1)
True
>>> np.isscalar([3.1])
False
>>> np.isscalar(False)
True
>>> np.isscalar('abcd')
True

31voto

Sukrit Kalra Punkte 33037

Während der Ansatz von @jamylak der bessere ist, hier ist ein alternativer Ansatz

>>> N=[2,3,5]
>>> P = 5
>>> type(P) in (tuple, list)
False
>>> type(N) in (tuple, list)
True

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X