Python: как определить, является ли переменная массивом или скалярным
У меня есть функция, которая принимает аргумент NBins
. Я хочу сделать вызов этой функции со скалярным 50
или массивом [0, 10, 20, 30]
. Как я могу идентифицировать внутри функции, какова длина NBins
? или иначе, если это скаляр или вектор?
Я пробовал это:
>>> 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()
>>>
Как вы видите, я не могу применить len
к P
, так как это не массив.... Есть ли что-то вроде isarray
или isscalar
в python?
спасибо
Ответы
Ответ 1
>>> isinstance([0, 10, 20, 30], list)
True
>>> isinstance(50, list)
False
Чтобы поддерживать любой тип последовательности, проверьте collections.Sequence
вместо list
.
note: isinstance
также поддерживает кортеж классов, проверить type(x) in (..., ...)
следует избегать и не нужно.
Вы также можете проверить not isinstance(x, (str, unicode))
Ответ 2
Предыдущие ответы предполагают, что массив является стандартным списком python. Поскольку кто-то часто использует numpy, я бы рекомендовал очень pythonic тест:
if hasattr(N, "__len__")
Ответ 3
Объединение @jamylak и @jpaddison3 отвечает вместе, если вам нужно быть устойчивым к массивам numpy в качестве ввода и обрабатывать их так же, как списки, вы должны использовать
import numpy as np
isinstance(P, (list, tuple, np.ndarray))
Это устойчиво против подклассов массивов list, tuple и numpy.
И если вы хотите быть надежным против всех других подклассов последовательности (а не только список и кортеж), используйте
import collections
import numpy as np
isinstance(P, (collections.Sequence, np.ndarray))
Зачем вам это делать с isinstance
и не сравнивать type(P)
с целевым значением? Вот пример, где мы делаем и изучаем поведение NewList
, тривиального подкласса списка.
>>> 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
Несмотря на то, что x
и y
сравниваются как равные, обработка их с помощью type
приведет к поведению. Однако, поскольку x
является экземпляром подкласса list
, использование isinstance(x,list)
дает желаемое поведение и обрабатывает x
и y
тем же способом.
Ответ 4
Есть ли эквивалент isscalar() в numpy? Да.
>>> np.isscalar(3.1)
True
>>> np.isscalar([3.1])
False
>>> np.isscalar(False)
True
Ответ 5
В то время как подход @jamylak является лучшим, вот альтернативный подход
>>> N=[2,3,5]
>>> P = 5
>>> type(P) in (tuple, list)
False
>>> type(N) in (tuple, list)
True
Ответ 6
Другой альтернативный подход (использование свойства class name):
N = [2,3,5]
P = 5
type(N).__name__ == 'list'
True
type(P).__name__ == 'int'
True
type(N).__name__ in ('list', 'tuple')
True
Не нужно ничего импортировать.
Ответ 7
Просто используйте size
вместо 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
Ответ 8
>>> N=[2,3,5]
>>> P = 5
>>> type(P)==type(0)
True
>>> type([1,2])==type(N)
True
>>> type(P)==type([1,2])
False
Ответ 9
Вы можете проверить тип данных переменной.
N = [2,3,5]
P = 5
type(P)
Он выдаст вам значение типа данных P.
<type 'int'>
Чтобы вы могли отличить это, это целое число или массив.
Ответ 10
Я удивлен, что такой базовый вопрос, похоже, не имеет прямого ответа на питоне.
Мне кажется, что почти все предложенные ответы используют какой-то тип
проверка, которая обычно не рекомендуется в python, и они, по-видимому, ограничены конкретным случаем (они терпят неудачу с разными численными типами или универсальными итерационными объектами, которые не являются кортежами или списками).
Для меня лучше работает импорт numpy и использование array.size, например:
>>> 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
Примечание:
>>> len(np.array([1,2]))
Out[5]: 2
а
>>> 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
Ответ 11
Вот лучший подход, который я нашел: Проверьте существование __len__
и __getitem__
.
Вы можете спросить почему? Причины включают в себя:
- Это обнаруживает несколько популярных объектов, которые в действительности являются массивами, включая собственный список Python и кортеж, NumPy ndarray и PyTorch Tensor.
- Другой популярный метод
isinstance(obj, abc.Sequence)
не работает на некоторых объектах, включая PyTorch Tensor, потому что они не реализуют __contains__
. - Использование collection.abc гораздо предпочтительнее, но, к сожалению, в Python collection.abc нет ничего, что проверяло бы только
__len__
и __getitem__
.
Так что без лишних слов:
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
Обратите внимание, что я добавил параметры по умолчанию, потому что большую часть времени вы можете рассматривать строки как значения, а не как массивы. Аналогично для кортежей.
Ответ 12
preds_test [0] имеет форму (128,128,1). Давайте проверим тип данных с помощью функции isinstance(). isinstance принимает 2 аргумента. 1-й аргумент - это данные. 2-й аргумент - это тип данных isinstance (preds_test [0], np.ndarray). Это означает, что preds_test [0] является массивом.