By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,965 Members | 1,962 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,965 IT Pros & Developers. It's quick & easy.

follow-up: python function taking scalar or list argument

P: 1
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:
Expand|Select|Wrap|Line Numbers
  1. def ddff_to_uv(dd, ff):
  2.     mydd = np.array(dd)
  3.     myff = np.array(ff)
  4.  
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:
Expand|Select|Wrap|Line Numbers
  1. import numpy as np
  2. def isvector(arg):
  3.     res = 0
  4.     if hasattr(arg, "__iter__"): res = 1
  5.     if isinstance(arg, np.ndarray): res = 2
  6.     return res
  7.  
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?
Oct 5 '11 #1
Share this Question
Share on Google+
1 Reply


bvdet
Expert Mod 2.5K+
P: 2,851
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:
Expand|Select|Wrap|Line Numbers
  1. import numpy as np
  2. def isvector(arg):
  3.     if isinstance(arg, np.ndarray):
  4.         return 2
  5.     elif hasattr(arg, "__iter__"):
  6.         return 1
  7.     return 0
Test for np.ndarray first, otherwise it will never be reached.
Oct 6 '11 #2

Post your reply

Sign in to post your reply or Sign up for a free account.