ValueError ao verificar se a variável é None ou numpy.array

104

Gostaria de verificar se a variável é None ou numpy.array. Eu implementei uma check_afunção para fazer isso.

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

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

Mas, esse código gera ValueError. Qual é o caminho direto?

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
fonte
2
Esta ValueErroré uma das numpyperguntas mais comuns . Isso significa que not aproduz um array booleano, com (neste caso) 2 valores. Este array booleano não pode ser usado como ifcondição! A is Nonealternativa é bom saber, mas você também deve compreender este erro.
hpaulj
@hpaulj: Não exatamente - você não pode sobrecarregar not, então o erro realmente ocorre quando nottenta tratar o array como um único booleano e descobre que não pode. Se tivesse sido ~a, isso teria usado a sobrecarga do NumPy e falhado ao iftentar usar o array negado como um único booleano.
user2357112 suporta Monica

Respostas:

174

Usar not apara testar se aé Nonepressupõe que os outros valores possíveis de atêm um valor verdade de True. No entanto, a maioria dos arrays NumPy não tem um valor verdadeiro e notnão pode ser aplicada a eles.

Se você quiser testar se um objeto o é None, a maneira mais geral e confiável é usar literalmente uma isverificação contra None:

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

Isso não depende de objetos possuírem um valor verdadeiro, então funciona com matrizes NumPy.

Observe que o teste tem que ser is, não ==. isé um teste de identidade de objeto. ==é o que quer que os argumentos digam, e os arrays NumPy dizem que é uma comparação de igualdade de elemento a elemento transmitida, produzindo um array booleano:

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

Por outro lado, se você quiser testar se um objeto é uma matriz NumPy, você pode testar seu tipo:

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

Você também pode usar isinstance, que também retornará Truepara subclasses desse tipo (se for o que você deseja). Considerando o quão terrível e incompatível np.matrixé, você pode não querer isso:

# Again, ndarray, not array, because array is a factory function.
if isinstance(a, np.ndarray):
    ...
else:
    ...    
Jerfov2
fonte
4
qual você recomenda que seja a "melhor" solução?
Monica Heddneck de
2

Se você está tentando fazer algo muito semelhante a is not None:, surge o mesmo problema. Ou seja, Numpy reclama que deve-se usar a.anyou a.all.

Uma solução alternativa é fazer:

if not (a is None):
    pass

Não é muito bonito, mas faz o trabalho.

mimoralea
fonte
0

Você pode ver se o objeto tem forma ou não

def check_array(x):
    try:
        x.shape
        return True
    except:
        return False
Itachi
fonte
1
votação negativa porque: outros tipos também podem ter o atributo de forma e podem até ter significados diferentes.
Herbert