Darren Haynes Darren Haynes - 3 months ago 14
Python Question

map with lambda vs map with function - how to pass more than one variable to function?

I wanted to learn about using

map
in python and a google search brought me to http://www.bogotobogo.com/python/python_fncs_map_filter_reduce.php which I have found helpful.

One of the codes on that page uses a for loop and puts
map
within that for loop in an interesting way, and the list used within the
map
function actually takes a list of 2 functions. Here is the code:

def square(x):
return (x**2)

def cube(x):
return (x**3)

funcs = [square, cube]

for r in range(5):
value = map(lambda x: x(r), funcs)
print value


output:

[0, 0]
[1, 1]
[4, 8]
[9, 27]
[16, 64]


So, at this point in that tutorial, I thought "well if you can write that code with a function on the fly (lambda), then it could be written using a standard function using
def
". So I changed the code to this:

def square(x):
return (x**2)

def cube(x):
return (x**3)

def test(x):
return x(r)

funcs = [square, cube]

for r in range(5):
value = map(test, funcs)
print value


I got the same output as the first piece of code, but it bothered me that variable
r
was taken from the global namespace and that the code is not tight functional programming. And there is where I got tripped up. Here is my code:

def square(x):
return (x**2)

def cube(x):
return (x**3)

def power(x):
return x(r)

def main():
funcs = [square, cube]
for r in range(5):
value = map(power, funcs)
print value

if __name__ == "__main__":
main()


I have played around with this code, but the issue is with passing into the function
def power(x)
. I have tried numerous ways of trying to pass into this function, but lambda has the ability to automatically assign
x
variable to each iteration of the list
funcs
.

Is there a way to do this by using a standard
def
function, or is it not possible and only lambda can be used?
Since I am learning python and this is my first language, I am trying to understand what's going on here.

Answer

You could nest the power() function in the main() function:

def main():
    def power(x):
        return x(r)

    funcs = [square, cube]
    for r in range(5):
        value = map(power, funcs)
        print value

so that r is now taken from the surrounding scope again, but is not a global. Instead it is a closure variable instead.

However, using a lambda is just another way to inject r from the surrounding scope here and passing it into the power() function:

def power(r, x):
    return x(r)

def main():
    funcs = [square, cube]
    for r in range(5):
        value = map(lambda x: power(r, x), funcs)
        print value

Here r is still a non-local, taken from the parent scope!

You could create the lambda with r being a default value for a second argument:

def power(r, x):
    return x(r)

def main():
    funcs = [square, cube]
    for r in range(5):
        value = map(lambda x, r=r: power(r, x), funcs)
        print value

Now r is passed in as a default value instead, so it was taken as a local. But for the purposes of your map() that doesn't actually make a difference here.