I have some objects which can either be floats (or integers) or tuples (or lists or arrays). Is it possible to use idiomatic Python to avoid writing an if
/elif
function? Right now I have
def f(attribute_a,attribute_b):
if type(attribute_a) == float or type(attribute_a) == int:
result = attribute_a + attribute_b
elif type(attribute_a) == list or type(attribute_a) == tuple or type(attribute_a) == array:
result = numpy.array([ attribute_a[i] + attribute_b[i] for i in range(len(attribute_a)) ])
return result
I'd like to avoid the elif stuff because sometimes I want attribute_a to be a float but attribute_b to be a list in which case, I'd like something like
result = numpy.array([ attribute_a + attribute_b[i] for i in range(len(attribute_b)) ])
since I have five different attributes, it's infeasible to write out the full set of possible if
loops for every possible combination of which one is a number and which is a list.
Any help is appreciated, Thanks, Sam
EDIT, 1/23/15: One idea is to define two new functions as follows
def general_value(x,i):
if type(x)==float or type(x)==int:
return x
elif type(x)==list or type(x)==tuple:
return x[i]
def general_len(x):
if type(x)==float or type(x)==int:
return 1
elif type(x)==list or type(x)==tuple:
return len(x)
(or with the various generalizations to isintance, etc.), and then plug these in where needed. Is this a reasonable hack, or is it somehow infelicitous?
Use isinstance where you can pass a tuple of types to avoid your multiple or's
:
if isinstance(attribute_a,(int,float))
...
elif isinstance(attribute_a,(list,tuple, array)):
If you can only have either two possible cases use if/else:
if isinstance(attribute_a,(int,float))
result = ...
else:
result = ...
You could use a conditional expression but your statement would be rather long:
result = attribute_a + attribute_b if isinstance(attribute_a,(int,float)) else numpy.array([ attribute_a[i] + attribute_b[i] for i in range(len(attribute_a)) ])
If you want to check two attributes for a group of possible match combinations:
if isinstance(attribute_a,(list,tuple,float) and isinstance(attribute_b,(float,list))):
Another way is to store the result of isinstance and negate the checks to avoid repeated calls:
a,b = if isinstance(attribute_a,(list,tuple) ,isinstance(attribute_b,float))
if a and b:
...
elif a and not b:
...
else:
....
If you want to check if either is a tuple,list, etc.. then you can use:
from collections import Iterable
def check(ele):
return isinstance(ele,Iterable) and not isinstance(ele,basestring)
Then:
if check(attribute_a) and check(attribute_b):
.....