I've got a function that returns a tuple, and I need to check if a specific element is in the tuple. I don't know types of elements will be in the tuple, but I know that I want an exact match. For example, I want
1 in (1, [0, 6], 0) --> True
1 in ([1], 0, 6]) --> False
This should be really straightforward, right? I just check 1 in tuple_output_from_function
.
This breaks if there is a numpy array as an element in the tuple
import numpy as np
s = tuple((2, [0, 6], 1))
4 in s --> False
t = tuple((2, np.arrary([0, 6]), 1))
4 in t --> ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
I expect the second case to return False because 4 is not in the tuple. Even if it were in the array, I would still expect False. I can do 0 in t[1]
without error. Why does this break, and how can I make my check robust to it without assuming that there will be a numpy array or having to check for it explicitly?
It breaks because if you in
operator, Python under the hood is using the equality operator (==
).
Consider this:
t = (2, np.array([0, 6]), 1)
v = 1
print(v in t)
Python checks each value in the tuple t
for equality. For numpy array the operation 1 == np.array([0, 6])
is another boolean array [False False]
. Python then checks if this result is truthy, which throws the exception you see.
You can use any()
and check if the current value you check is the type of the value is int
:
t = (2, np.array([0, 6]), 1)
v = 1
x = any(v == i for i in t if isinstance(i, int))
print(x)
Prints:
True