ValueError при проверке, является ли переменная None или numpy.array

104

Я хотел бы проверить, является ли переменная None или numpy.array. Я реализовал check_aфункцию для этого.

def check_a(a):
    if not a:
        print "please initialize a"

a = None
check_a(a)
a = np.array([1,2])
check_a(a)

Но этот код вызывает ValueError. Какой прямой путь?

ValueError                                Traceback (most recent call last)
<ipython-input-41-0201c81c185e> in <module>()
      6 check_a(a)
      7 a = np.array([1,2])
----> 8 check_a(a)

<ipython-input-41-0201c81c185e> in check_a(a)
      1 def check_a(a):
----> 2     if not a:
      3         print "please initialize a"
      4 
      5 a = None

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
rkjt50r983
источник
2
Это ValueErrorодин из самых частых numpyвопросов. Это означает, что not aсоздается логический массив с (в данном случае) двумя значениями. Этот логический массив нельзя использовать в качестве ifусловия! is NoneАльтернатива хорошо знать, но вы должны также понять эту ошибку.
hpaulj
@hpaulj: Не совсем так - вы не можете перегрузить not, поэтому ошибка на самом деле возникает, когда notпытается обработать массив как одно логическое значение и обнаруживает, что это невозможно. Если бы это было так ~a, это использовало бы перегрузку NumPy и не удалось ifбы использовать отрицательный массив как одно логическое значение.
user2357112 поддерживает Монику

Ответы:

177

Использование not aдля проверки того a, Noneпредполагает ли это, что другие возможные значения aимеют значение истинности True. Однако большинство массивов NumPy вообще не имеют значения истинности и notне могут быть к ним применены.

Если вы хотите проверить, существует ли объект None, наиболее общий и надежный способ - буквально использовать isпроверку None:

if a is None:
    ...
else:
    ...

Это не зависит от объектов, имеющих значение истинности, поэтому работает с массивами NumPy.

Учтите, что тест должен быть is, а не ==. isэто тест на идентичность объекта. ==это то, что аргументы говорят, а массивы NumPy говорят, что это транслируемое поэлементное сравнение равенства, производящее логический массив:

>>> a = numpy.arange(5)
>>> a == None
array([False, False, False, False, False])
>>> if a == None:
...     pass
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: The truth value of an array with more than one element is ambiguous.
 Use a.any() or a.all()

С другой стороны, если вы хотите проверить, является ли объект массивом NumPy, вы можете проверить его тип:

# Careful - the type is np.ndarray, not np.array. np.array is a factory function.
if type(a) is np.ndarray:
    ...
else:
    ...

Вы также можете использовать isinstance, который также будет возвращен Trueдля подклассов этого типа (если вы этого хотите). Учитывая, насколько это ужасно и несовместимо np.matrix, вы можете этого не захотеть:

# Again, ndarray, not array, because array is a factory function.
if isinstance(a, np.ndarray):
    ...
else:
    ...    
Jerfov2
источник
4
какое решение вы порекомендуете "лучшее"?
Моника Хедднек
2

Если вы пытаетесь сделать что-то очень похожее:, a is not Noneвозникает та же проблема. То есть Numpy жалуется, что нужно использовать a.anyили a.all.

Обходной путь:

if not (a is None):
    pass

Не очень красиво, но работает.

миморалея
источник
0

Вы можете увидеть, имеет ли объект форму или нет

def check_array(x):
    try:
        x.shape
        return True
    except:
        return False
Итачи
источник
1
отвергнуты, потому что: другие типы также могут иметь атрибут shape, и они могут даже иметь другое значение.
Герберт,