3

I am using Python3.6 and am trying to figure out ways in which we can use map with multiple arguments.

When I run,

def multiply(x, y, z):
    return x * y * z

products = map(multiply, [3,6], [1,8], [3,5])

list(products) returns [9, 240] as expected

However, when I specify a default value for z,

def multiply(x, y, z = [3,5]):
    return x * y * z

products = map(multiply, [3,6], [1,8])

list(product) returns

[[3, 5, 3, 5, 3, 5],
 [3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5,
  3,
  5]]

Why does Python differ in the way it runs map in the two scenarios?

Isaac
  • 100
  • 1
  • 7

3 Answers3

2

Try:

l=iter([3,5])
def multiply(x, y, z = l):
    return x * y * next(z)

products = map(multiply, [3,6], [1,8])

Then list(products) would be: [9, 240]

Explanation:

Your code doesn't work because you're multiplying a number with a list (so basically it will be a list repeated n times), you need to get always the next value, so do next to the iter of the list

See: Python: next() function

U13-Forward
  • 69,221
  • 14
  • 89
  • 114
  • This works. Although do you know why the code multiplies `z' to `x*y` when z does not have a default value, and repeats `z` `x*y` times when z has a default value? – Isaac Aug 18 '18 at 05:13
  • 1
    @Isaac i don't fully understand what you mean, but as you know in the function you're doing something to a __list__ not a __int__ so it basically is `x*y*[3,5]` – U13-Forward Aug 18 '18 at 05:16
1

When you set the default value of z during execution with map this happens:

3 * 1 * [3,5]
6 * 8 * [3,5]

Therefore your output, for map to work as you intend you should explicitly give the list as one of it arguments and in your case the default value of z is not a direct argument of map. Hope this makes sense.

ikuamike
  • 339
  • 1
  • 6
1

I think it should use reduce rather than map.This link explain difference between reduce and map.Using reduce it should be

import functools
expected=functools.reduce(lambda acc,current:[acc[0]*current[0],acc[1]*current[1]],([3,6], [1,8], [3,5]))
print(expected) # [9, 240]

According to this doc.reduce is roughly equivalent to:

def reduce(function, iterable, initializer=None):
    it = iter(iterable)
    if initializer is None:
        value = next(it)
    else:
        value = initializer
    for element in it:
        value = function(value, element)
    return value
XX 吕
  • 186
  • 1
  • 8
  • I agree, but if I were to use reduce, I think this might be cleaner: `expected = functools. reduce(lambda x, y : [z[0]*z[1] for z in zip(x,y)] , ([3,6], [1,8], [3,5]))` Thanks for the idea. – Isaac Aug 19 '18 at 07:27