0

If I define a function as:

def somefunc(a, b, c):
    out = [ (a+b)/c for a, b, c in zip(a, b, c) ]
    return out

all the arguments must be lists of the same length, otherwise I would get the output truncated. Example: somefunc([1, 2], [3, 4], [5, 5]) would give me [0.8, 1.2].

It would be really convenient to be able to input a single number instead of a list when it doesn't change, like: somefunc([1, 2], [3, 4], 5). Of course any of the arguments can be reduced to a single value instead of a list. This can be achieved using numpy with this function definition:

from numpy import array

def somefunc(a, b, c):

    a=array(a)
    b=array(b)
    c=array(c)

    out = (a+b)/c
    return out

Is there a way to do the same without numpy (and without converting all the arguments one by one)?

2
  • No, zip expects iterable arguments; if your function takes non-iterable arguments, you will have to convert them. Commented Jul 23, 2014 at 15:55
  • Note: If you want NumPy features, the easiest way is going to be to use NumPy. Each feature can of course be implemented without NumPy, but if that was easy, NumPy wouldn't be here. Commented Jul 25, 2014 at 8:26

2 Answers 2

2

Sure, you can make an infinite list repeating any argument that is not a list in itself.

from itertools import repeat

def broadcast(o):
    return o if hasattr(o, '__iter__') else repeat(o)

def somefunc(a, b, c):
    out = [ (a+b)/c for a, b, c in zip(broadcast(a), broadcast(b), broadcast(c)) ]
    return out

>>> somefunc([1, 2], [3, 4], 5)
[0.8, 1.2]
>>> somefunc([1, 2], 5, [3, 4])
[2.0, 1.75]
>>> 
Sign up to request clarification or add additional context in comments.

3 Comments

Ok, but it doesn't work if the scalar argument is not the last: somefunc([1, 2], 3, [5, 5])
I think you commented the wrong answer. rroowwllaanndd's solution does not work if either of the first two arguments are scalars. Mine does.
ooops you are right, but now the other has been edited and it works as well. thanks
1

Numpy is awesome, and is perfect for vectorizing computaions like the one you posted. I'd recommend you do use it.

Also, you don't need to convert all the arguments to arrays, only one, and it is better to use asarray, which would avoid creating a new copy when one isn't necessary.

def somefunc(a, b, c):
    return (asarray(a) + b) / c

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.