it-swarm.com.ru

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?

спасибо

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

Для поддержки любого типа последовательности установите флажок collections.Sequence вместо list.

note : isinstance также поддерживает Tuple классов, проверка type(x) in (..., ...) должна быть исключена и не нужна.

Вы также можете проверить not isinstance(x, (str, unicode))

296
jamylak

Предыдущие ответы предполагают, что массив представляет собой стандартный список Python. Как человек, который часто использует numpy, я бы порекомендовал очень Pythonic тест:

if hasattr(N, "__len__")
95
jpaddison3

Комбинируя ответы @jamylak и @ jpaddison3 вместе, если вам нужно быть устойчивым к массивным массивам в качестве входных данных и обрабатывать их так же, как списки, вы должны использовать

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

Это устойчиво к подклассам списков, массивов 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 таким же образом.

33
scottclowe

Есть ли в numpy эквивалент isscalar ()? Да. 

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

В то время как подход @ jamylak лучше, вот альтернативный подход

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

Просто используйте 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
3
Mathieu Villion

Другой альтернативный подход (использование класса имя свойство):

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

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

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

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

Не нужно ничего импортировать.

3
Marek

Вы можете проверить тип данных переменной.

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

Он выдаст вас как тип данных P.

<type 'int'>

Так что вы можете различить, что это целое число или массив.

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

Я удивлен, что такой основной вопрос, кажется, не имеет немедленного ответа в python .... Мне кажется, что почти все предложенные ответы используют какой-то тип проверки., Который обычно не рекомендуется в 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
1
Vincenzooo

preds_test [0] имеет форму (128,128,1). Давайте проверим тип данных с помощью функции isinstance (). isinstance принимает 2 аргумента. 1-й аргумент - это данные. 2-й аргумент - это тип данных isinstance (preds_test [0], np.ndarray). Это означает, что preds_test [0] является массивом.

0
Sumanth Meenan

Вот лучший подход, который я нашел: Проверьте наличие __len__ и __getitem__

Вы можете спросить почему? Причины включают в себя:

  1. Это обнаруживает несколько популярных объектов, которые в действительности являются массивами, включая нативный список Python и Tuple, NumPy ndarray и PyTorch Tensor. 
  2. Другой популярный метод isinstance(obj, abc.Sequence) терпит неудачу на некоторых объектах, включая Tensor PyTorch, потому что они не реализуют __contains__.
  3. Использование 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

Обратите внимание, что я добавил параметры по умолчанию, потому что большую часть времени вы можете рассматривать строки как значения, а не как массивы. Аналогично для кортежей.

0
Shital Shah