Python: cómo identificar si una variable es una matriz o un escalar
Tengo una función que toma el argumento NBins
. Quiero hacer una llamada a esta función con un escalar 50
o una matriz [0, 10, 20, 30]
. ¿Cómo puedo identificar dentro de la función cuál NBins
es la longitud? o dicho de otra manera, ¿si es un escalar o un vector?
Probé esto:
>>> 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()
>>>
Como puede ver, no puedo aplicar len
a P
, ya que no es una matriz.... ¿Existe algo como isarray
o isscalar
en Python?
gracias
>>> import collections.abc
>>> isinstance([0, 10, 20, 30], collections.abc.Sequence)
True
>>> isinstance(50, collections.abc.Sequence)
False
nota : isinstance
también admite una tupla de clases, type(x) in (..., ...)
se debe evitar la verificación y es innecesaria.
Quizás también quieras comprobarnot isinstance(x, (str, unicode))
Como lo señaló @ 2080 y también aquí , esto no funcionará para numpy
matrices. p.ej.
>>> 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
En cuyo caso puedes probar la respuesta de @jpaddison3 :
>>> hasattr(np.array([1, 2, 3]), "__len__")
True
>>> hasattr([1, 2, 3], "__len__")
True
>>> hasattr((1, 2, 3), "__len__")
True
Sin embargo, como se indica aquí , esto tampoco es perfecto y clasificará incorrectamente (al menos según yo) los diccionarios como secuencias, mientras que isinstance
with collections.abc.Sequence
clasifica correctamente:
>>> 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
Puede personalizar su solución con algo como esto y agregar más tipos isinstance
según sus necesidades:
>>> isinstance(np.array([1, 2, 3]), (collections.abc.Sequence, np.ndarray))
True
>>> isinstance([1, 2, 3], (collections.abc.Sequence, np.ndarray))
True
Las respuestas anteriores suponen que la matriz es una lista estándar de Python. Como alguien que usa numpy con frecuencia, recomendaría una prueba muy pitónica de:
if hasattr(N, "__len__")
Combinando las respuestas de @jamylak y @ jpaddison3, si necesita ser robusto contra matrices numerosas como entrada y manejarlas de la misma manera que las listas, debe usar
import numpy as np
isinstance(P, (list, tuple, np.ndarray))
Esto es robusto contra subclases de listas, tuplas y matrices numpy.
Y si también desea ser robusto frente a todas las demás subclases de secuencia (no solo lista y tupla), use
import collections
import numpy as np
isinstance(P, (collections.Sequence, np.ndarray))
¿Por qué debería hacer las cosas de esta manera isinstance
y no compararlas type(P)
con un valor objetivo? A continuación se muestra un ejemplo en el que creamos y estudiamos el comportamiento de NewList
una subclase trivial de lista.
>>> 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
A pesar x
de y
compararlos como iguales, manejarlos type
resultaría en un comportamiento diferente. Sin embargo, dado que x
es una instancia de una subclase de list
, el uso isinstance(x,list)
proporciona el comportamiento deseado y lo trata x
de y
la misma manera.
¿Existe un equivalente a isscalar() en numpy? Sí.
>>> np.isscalar(3.1)
True
>>> np.isscalar([3.1])
False
>>> np.isscalar(False)
True
>>> np.isscalar('abcd')
True