How best to write a function that can accept either scalar floats or numpy vectors (1-d array), and return a scalar, 1-d array, or 2-d array, depending on the input?
The function is expensive and is called often, and I don't want to place a burden on the caller to do special casts to the arguments or return values. It only needs to treat numbers (not lists or other iterable things).
np.vectorize might be slow (Broadcasting a python function on to numpy arrays) and other answers (Getting a Python function to cleanly return a scalar or list, depending on number of arguments) and np.asarray (A python function that accepts as an argument either a scalar or a numpy array) does not help with getting dimensions required for the output array.
This type of code would work in Matlab, Javascript, and other languages:
import numpy as np
def func( xa, ya ):
# naively, I thought I could do:
xy = np.zeros( ( len(xa), len(ya) ) )
for j in range(len( ya )):
for i in range(len( xa )):
# do something complicated
xy[i,j] = x[i]+y[j]
return xy
Works fine for arrays:
x = np.array([1., 2.])
y = np.array([2., 4.])
xy = func(x,y)
print xy
[[ 3. 5.]
[ 4. 6.]]
But does not work for scalar floats:
x = 1.
y = 3.
xy = func(x,y)
print xy
<ipython-input-64-0f85ad330609> in func(xa, ya)
4 def func( xa, ya ):
5 # naively, I thought I could do:
----> 6 xy = np.zeros( ( len(xa), len(ya) ) )
7 for j in range(len( ya )):
8 for i in range(len( xa )):
TypeError: object of type 'float' has no len()
Using np.asarray in a similar function gives:
<ipython-input-63-9ae8e50196e1> in func(x, y)
5 xa = np.asarray( x );
6 ya = np.asarray( y );
----> 7 xy = np.zeros( ( len(xa), len(ya) ) )
8 for j in range(len( ya )):
9 for i in range(len( xa )):
TypeError: len() of unsized object
What is the fast, elegant, and pythonic approach?