(EDIT: to include a more general and perhaps cleaner approach)
One way around it is to implement a NumPy safe version of in:
import numpy as np
def in_np(x, items):
for item in items:
if isinstance(x, np.ndarray) and isinstance(item, np.ndarray) \
and x.shape == item.shape and np.all(x == item):
return True
elif isinstance(x, np.ndarray) or isinstance(item, np.ndarray):
pass
elif x == item:
return True
return False
x = np.array([1, 1])
a = [x, 1]
for y in (x, 0, 1, x + 1, np.array([1, 1, 1])):
print(in_np(y, a))
# True
# False
# True
# False
# False
Or, even better, to write a version of in with an arbitrary comparison (possibly defaulting to the default in behavior), and then make use of np.array_equal() which has a semantic that is compliant with the expected behavior for ==. In code:
import operator
def in_(x, items, eq=operator.eq):
for item in items:
if eq(x, item):
return True
return False
x = np.array([1, 1])
a = [x, 1]
for y in (x, 0, 1, x + 1, np.array([1, 1, 1])):
print(in_(y, a, np.array_equal))
# True
# False
# True
# False
# False
Finally, note that items can be any iterable, but the complexity of the operation will not be O(1) for hashing containers like set(), although it would still be giving correct results:
print(in_(1, {1, 2, 3}))
# True
print(in_(0, {1, 2, 3}))
# False
in_(1, {1: 2, 3: 4})
# True
in_(0, {1: 2, 3: 4})
# False
ValueError: The truth value of an array with more than one element is ambiguous.even with the first checkx in a