Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass non-iterable variables to a function evaluated with map()

I am working in python and trying to convert a function with this structure:

def func(g,h,iterable):
 return iterable*(g+h)

for iterable in range(20):
  print func(2,3,iterable)

Into a mapped function:

def func(g,h,iterable):
 return iterable*(g+h)

print map(func,2,3,range(20)) #does not work...

The issue I am having is passing constants through the map() function, currently I don't know how to do it.

I want this structure so I can easily use the Ipython parallelism tools.

Assume:

  • The actual function completion over all iterables takes ~1.5hr (thus the desire for using a parallel map() function
  • The function is complex and cannot use list comprehension

Essentially, if it wasn't already obvious I am a MATLAB programmer making the leap to python and looking for a good substitute for the parfor function in matlab.

like image 474
Rob andrews Avatar asked Jun 04 '13 17:06

Rob andrews


Video Answer


3 Answers

For one thing, if you map your function over a range, no parameter is an iterable.

To your question, you can bind positional parameters (from left to right) to a function using functools.partial

def func(g,h,i):
    return i*(g+h)

print map(functools.partial(func, 2,3), range(20))

# [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95]

For binding any positional parameter, use a lambda expression like stated in hkpeprah's answer.

like image 75
Thomas Fenzl Avatar answered Oct 07 '22 16:10

Thomas Fenzl


If you know the parameters ahead of time, you can use a lambda like

f = lambda lst: func(2,3,lst)
map(f, range(20))

Alternatively, if you don't know the parameters, you could wrap a lambda expression

f = lambda x: lambda y: lambda lst: func(x,y,lst)
f = f(2)
f = f(3)
map(f, range(20))
like image 35
Ford Avatar answered Oct 07 '22 15:10

Ford


You could use closures:

def initFunction(g, h):
    def funct(value):
        return g * h * value
    return funct

myFunct = initFunction(g, h)
mapped = map(myFunct, range(20)) 

PS. I'm guessing you're using python 3.x for this, or else xrange + generator comprehension would be much better than range for large values! (equivalent code in 2.7 btw):

def initFunction(g, h):
    def funct(value):
        return g * h * value
    return funct

myFunct = initFunction(g, h)
mapped = (myFunct(i) for i in xrange(20)) 
like image 1
James Avatar answered Oct 07 '22 17:10

James