I have a function that can accept two optional np.array
as arguments. In case both are passed the function should do perform some task.
def f(some_stuff, this=None, that=None):
...do something...
if this and that:
perform_the_task()
This works as expected if none of the optional arguments are passed. If I pass a np.array
then I obtain the error
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Is there more compact way of checking if the extra args are passed? I guess I can safely assume that if they are passed, then they are going to be np.array
.
Firstly, you can assume that they will be the right type (especially if you're the only one using the code). Just add it to the documentation. Type checking of arguments Python (the accepted answer even sighs as they explain duck typing)
The exception you're getting is common and is all over SO, like ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all().
In your case,
if this is not None and that is not None
will accomplish what you want. The issue is not the "and", so much as the fact that the array
if np.array([True, False]):
foo()
is ambiguous from numpy's point of view, in that some of the array's values are true, but not all of them... so what should it return?. This behaviour is notably inconsistent with the behaviour of lists (I believe your current code follows the SO-recommended way of checking if a list is None or empty)
If you're thinking of a Java-esk way of overloading your function depending on how many arguments are passed, you're not thinking pythonically enough. You can certainly send whatever comes after that conditional to another function to "concisely" deal with it. The following would also be fine
def f(some_stuff, this=None, that=None):
...do something...
perform_the_task(this,that)
def perform_the_task(this,that):
if this is None or that is None: return
raise NotImplementedException
As you can see in the sidebar this ValueError
has come up before - many times.
The core of the problem is that numpy arrays can return multiple truth values, while many Python operations expect just one.
I'll illustrate:
In [140]: this=None
In [141]: if this:print 'yes'
In [142]: if this is None: print 'yes'
yes
In [143]: this=np.array([1,2,3])
In [144]: if this: print 'yes'
...
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
In [145]: if this is None: print 'yes'
In [146]: this and this
...
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
In [147]: [1,2,3] is None
Out[147]: False
In [148]: this is None
Out[148]: False
In [149]: [1,2,3]==3 # one value
Out[149]: False
In [150]: this == 3 # multiple values
Out[150]: array([False, False, True], dtype=bool)
Logical operations like not
usually return a simple True/False, but for arrays, they return a value for each element of the array.
In [151]: not [1,2,3]
Out[151]: False
In [152]: not None
Out[152]: True
In [153]: not this
...
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
In your function, if you don't give f
2 or more arguments, this
and that
will have value None
. The safe way to test that is with is None
or is not None
:
def f(some_stuff, this=None, that=None):
...do something...
if this is not None and that is not None:
perform_the_task()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With