ValueError podczas sprawdzania, czy zmienna ma wartość None lub numpy.array

105

Chciałbym sprawdzić, czy zmienna to None lub numpy.array. Zaimplementowałem check_afunkcję, aby to zrobić.

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

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

Ale ten kod wywołuje ValueError. Jaka jest prosta droga?

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
źródło
2
To ValueErrorjedno z najczęściej numpyzadawanych pytań. Oznacza to, że not atworzy tablicę logiczną zawierającą (w tym przypadku) 2 wartości. Ta tablica logiczna nie może być używana jako ifwarunek! is NoneAlternatywą jest dobrze wiedzieć, ale należy również zrozumieć ten błąd.
hpaulj
@hpaulj: Niezupełnie - nie możesz przeciążać not, więc błąd faktycznie występuje, gdy notpróbuje traktować tablicę jako pojedynczą wartość logiczną i okazuje się, że nie może. Gdyby tak było ~a, wykorzystałoby to przeciążenie NumPy i zakończyło się niepowodzeniem przy ifpróbie użycia zanegowanej tablicy jako pojedynczej wartości logicznej.
user2357112 obsługuje Monikę

Odpowiedzi:

177

Korzystanie not aaby sprawdzić, czy ato Nonezakłada, że inne możliwe wartości amają wartość prawdy True. Jednak większość tablic NumPy w ogóle nie ma wartości prawdziwości i notnie można ich do nich zastosować.

Jeśli chcesz sprawdzić, czy obiekt jest None, najbardziej ogólnym i niezawodnym sposobem jest dosłowne użycie issprawdzenia None:

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

Nie zależy to od obiektów mających wartość prawdy, więc działa z tablicami NumPy.

Zauważ, że test musi być is, nie ==. isjest testem tożsamości obiektu. ==jest cokolwiek mówią argumenty, a tablice NumPy mówią, że jest to transmitowane elementowe porównanie równości, tworząc tablicę boolowską:

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

Z drugiej strony, jeśli chcesz sprawdzić, czy obiekt jest tablicą NumPy, możesz przetestować jego typ:

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

Możesz także użyć isinstance, który zwróci również Truedla podklas tego typu (jeśli tego chcesz). Biorąc pod uwagę, jak straszne i niekompatybilne np.matrixjest to, możesz tego nie chcieć:

# Again, ndarray, not array, because array is a factory function.
if isinstance(a, np.ndarray):
    ...
else:
    ...    
Jerfov2
źródło
4
które polecasz jest „najlepszym” rozwiązaniem?
Monica Heddneck
2

Jeśli próbujesz zrobić coś bardzo podobnego: a is not Nonepojawia się ten sam problem. Oznacza to, że Numpy narzeka, że ​​należy użyć a.anylub a.all.

Sposób obejścia problemu:

if not (a is None):
    pass

Niezbyt ładna, ale spełnia swoje zadanie.

mimoralea
źródło
0

Możesz zobaczyć, czy obiekt ma kształt, czy nie

def check_array(x):
    try:
        x.shape
        return True
    except:
        return False
Itachi
źródło
1
odrzucone, ponieważ: inne typy również mogą mieć atrybut kształtu, a nawet mogą mieć inne znaczenie.
Herbert