title: Python function that handles scalar or arrays
body: <p>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?</p>
  
  <p>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).</p>
  
  <p>np.vectorize might be slow (<a href="https://stackoverflow.com/questions/5197650/broadcasting-a-python-function-on-to-numpy-arrays">Broadcasting a python function on to numpy arrays</a>) and other answers (<a href="https://stackoverflow.com/questions/4029001/getting-a-python-function-to-cleanly-return-a-scalar-or-list-depending-on-numbe">Getting a Python function to cleanly return a scalar or list, depending on number of arguments</a>) and np.asarray (<a href="https://stackoverflow.com/questions/26542615/a-python-function-that-accepts-as-an-argument-either-a-scalar-or-a-numpy-array">A python function that accepts as an argument either a scalar or a numpy array</a>) does not help with getting dimensions required for the output array.</p>
  
  <p>This type of code would work in Matlab, Javascript, and other languages:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Works fine for arrays:</p>
  
  <pre><code>x = np.array([1., 2.])
  y = np.array([2., 4.])
  xy = func(x,y)
  print xy
  
  [[ 3.  5.]
   [ 4.  6.]]
  </code></pre>
  
  <p>But does not work for scalar floats:</p>
  
  <pre><code>x = 1.
  y = 3.
  xy = func(x,y)
  print xy
  
  &lt;ipython-input-64-0f85ad330609&gt; in func(xa, ya)
        4 def func( xa, ya ):
        5     # naively, I thought I could do:
  ----&gt; 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()
  </code></pre>
  
  <p>Using np.asarray in a similar function gives:</p>
  
  <pre><code>&lt;ipython-input-63-9ae8e50196e1&gt; in func(x, y)
        5     xa = np.asarray( x );
        6     ya = np.asarray( y );
  ----&gt; 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
  </code></pre>
  
  <p>What is the fast, elegant, and pythonic approach?</p>