title: How to properly generalize functions operating on vectors to those that operate on multi-dimensional arrays?
body: <p>I often end up implementing routines that operate on 1-D arrays, and then generalize them so that, if they are called on matrices, they treat each row independently.  For example, suppose we want a function that subtracts the mean of a vector from it, and then does that on every row of a matrix, if its input has more than one dimensions.  This can be implemented as follows:</p>
  
  <pre><code>import numpy as np
  
  def _sub_mean(a):
      """ Subtract the mean from vector elements """
  
      assert isinstance(a, np.ndarray) and a.ndim == 1
  
      return a - np.mean(a)
  
  def sub_mean(a):
      """ Subtract the mean
  
      If `a` is a 1D array it returns a 1D array (obtained by subtracting the
      mean of `a` from each of its elements).  If `a` has more than one dimension
      each row is treated separately
  
      """
  
      a = np.asanyarray(a)
  
      if a.ndim &lt;= 1:
          a = np.atleast_1d(a)
  
          return np.squeeze(_sub_mean(a))
  
      retval = np.empty(a.shape)
  
      for idx in np.ndindex(*a.shape[:-1]):
          retval[idx] = _sub_mean(a[idx])
  
      return retval
  </code></pre>
  
  <p>Here are a few examples of the output of <code>sub_mean</code>:</p>
  
  <pre><code>&gt;&gt;&gt; sub_mean(5)
  array(0.)
  &gt;&gt;&gt; sub_mean([1, 2])
  array([-0.5,  0.5])
  &gt;&gt;&gt; sub_mean([[1, 2], [4, 6]])
  array([[-0.5,  0.5],
         [-1. ,  1. ]])
  &gt;&gt;&gt; 
  </code></pre>
  
  <p>Note that the 'core' computation is taking place in the private function <code>_sub_mean</code>.  Indeed the same code in <code>sub_mean</code> can be used to generalize any function that operates on 1D arrays to one that operates on arbitrary number of dimensions, by replacing <code>_sub_mean</code>.  Also one can think of further generalization, for example adding an <code>axis</code> argument that specifies on which axis the function operates and/or possibility of operating on the flattened input array.</p>
  
  <p>I was wondering if NumPy already provides a decorator to generalize functions that operate on vectors to those that operate on more-than-one-dimensional arrays?  I.e., if I can replace the above code by:</p>
  
  <pre><code>import numpy as np
  
  @np.some_decorator
  def sub_mean(a):        
      """ Subtract the mean
  
      If `a` is a 1D array it returns a 1D array (obtained by subtracting the
      mean of `a` from each of its elements).  If `a` has more than one dimension
      each row is treated separately  """
  
  
      assert isinstance(a, np.ndarray) and a.ndim == 1
  
      return a - np.mean(a)
  </code></pre>
  
  <p>(and, obviously, get the same outputs.)</p>
  
  <hr>
  
  <p>UPDATE:  I ended up writing the following decorator:</p>
  
  <pre><code>class _Expand:
      def __init__(self, func1d):
          functools.update_wrapper(self, func1d)
          self._func1d = func1d
  
      def __call__(self, arr, *args, **kwargs):
          arr = np.asanyarray(arr)
  
          axis = kwargs.pop('axis', -1)
  
          return np.apply_along_axis(self._func1d, axis, arr, *args, **kwargs)
  </code></pre>
  
  <p>which would then enable me to write <code>sub_mean</code> (or any other complex function that operates on 1D arrays) as:</p>
  
  <pre><code>@_Expand
  def sub_mean(a):        
      """ Subtract the mean
  
      If `a` is a 1D array it returns a 1D array (obtained by subtracting the
      mean of `a` from each of its elements).  If `a` has more than one dimension
      each row is treated separately  """
  
  
      assert isinstance(a, np.ndarray) and a.ndim == 1
  
      return a - np.mean(a)
  </code></pre>
  
  <p>(Note that <code>_Expand</code> allows to pick the axis along which the operation is performed --- that's slightly more generic than what I needed.)</p>
  
  <p>Yet, I would still be curious to know if such a decorator is already implemented in NumPy?</p>