follow-up: python function taking scalar or list argument

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • MartinS
    New Member
    • Oct 2011
    • 1

    follow-up: python function taking scalar or list argument

    Hi,

    as a newby to python but otherwise not totally unexperienced programmer, I would like to bring up the question once more how I can best determine if a function argument is a) scalar or vector, and b) a "simple" python float or a numpy float type.

    The previous post on this topic had a simple function "twice (x)" which can easily be vectorized through list comprehension, for example. In my case, I am working on a function that converts wind direction and speed to vector components u and v (and its inverse counterpart). This entails a couple of "if" checks and more than one line of code.

    I wish to apply this function either in a "pocket calculator" fashion, where a user can call it with simple scalar arguments (example: print ddff_to_uv(230. ,8.5)) or in other programs which might read very lengthy data vectors (for example from a weather model) nand these would typically be numpy ndarrays then.

    As far as I can see, the easiest solution would be to simply package any argument into an ndarray:
    Code:
    def ddff_to_uv(dd, ff):
        mydd = np.array(dd)
        myff = np.array(ff)
    and then proceed without hassle. However, this seems extremly inefficient if the input is already a (very large) ndarray.

    If I want to be more smart about this, I don't see a good way of testing yet:
    * checking dd.size only works if dd is a numpy array or float (other types are not of interest), a common python float doesn't have a size attribute.
    * testing for isinstance(dd, list) doesn't work on a numpy array.
    * testing for isinstance(dd, (list, ndarray)) could work, but then there may well be other derived types coming up which I don't know about yet.
    * hasattr(dd, '__iter__') would return true for both an ndarray and a python list; so this seems to point in the right direction. But I cannot use array syntax on a python list of float values, so I would need to convert them into ndarray first -- which again seems inefficient if dd already is an ndarray.

    My present solution is the following function:
    Code:
    import numpy as np
    def isvector(arg):
        res = 0
        if hasattr(arg, "__iter__"): res = 1
        if isinstance(arg, np.ndarray): res = 2
        return res
    Thus, 2 is returned for a numpy array, 1 for any other iterable (which I then assume to be a list of numerical values), and 0 for any non-iterable (which I assume to be a scalar float (or integer) value.

    Any comments or siggestions for improvement?
  • bvdet
    Recognized Expert Specialist
    • Oct 2006
    • 2851

    #2
    I don't know much about numpy. Having said that it seems like your solution is well thought out. I can offer a slight improvement though:
    Code:
    import numpy as np
    def isvector(arg):
        if isinstance(arg, np.ndarray):
            return 2
        elif hasattr(arg, "__iter__"):
            return 1
        return 0
    Test for np.ndarray first, otherwise it will never be reached.

    Comment

    Working...