424,054 Members | 1,055 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,054 IT Pros & Developers. It's quick & easy.

help with map function

P: n/a
In the book 'Text Processing Python,' they present a function that I'm
having a real hard time understanding.

apply_each = lambda fns, args=[]: map(apply, fns, [args]*len(fns))
I understand that the lamda statement is passing a function that
accepts a function and an iterable variable as arguments.

The function passed by lamda is a map statement that maps the function
in the arguement list against each item in the iterable variable.

However, I don't understand what is happening in the 3rd arguement of
map though. What does [args]*len(fns) do?
Jul 18 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a
Michael wrote:
In the book 'Text Processing Python,' they present a function that I'm
having a real hard time understanding.

apply_each = lambda fns, args=[]: map(apply, fns, [args]*len(fns))
A lambda creates an anonymous function. Assigning a lambda directly to a
variable is simply an exercise in obfuscation. The same code can be more
clearly expressed:

def apply_each(fns, args=[]):
return map(apply, fns, [args]*len(fns))
These days you can express the same thing more clearly with a list
comprehension:

def apply_each(fns, args=[]):
return [ fn(*args) for fn in fns ]

In general it would probably be better to define it as:

def apply_each(fns, *args, **kw):
return [ fn(*args, **kw) for fn in fns ]

although this changes slightly how you call it.

I understand that the lamda statement is passing a function that
accepts a function and an iterable variable as arguments.

The function passed by lamda is a map statement that maps the function
in the arguement list against each item in the iterable variable.

However, I don't understand what is happening in the 3rd arguement of
map though. What does [args]*len(fns) do?

[args]*len(fns) is equivalent to [args, args, args, ...] where args is
repeated as often as there are elements in the list. It means that every
time apply is called it gets one of the functions and the args value as its
parameters.







Jul 18 '05 #2

P: n/a
Duncan Booth wrote:
A lambda creates an anonymous function. Assigning a lambda directly to a variable is simply an exercise in obfuscation. The same code can be more clearly expressed:

def apply_each(fns, args=[]):
return map(apply, fns, [args]*len(fns))
I agree. I was so busy trying to wrap my head around this statement,
that I realize it was more complex than it had to be.
These days you can express the same thing more clearly with a list
comprehension:

def apply_each(fns, args=[]):
return [ fn(*args) for fn in fns ]

In general it would probably be better to define it as:

def apply_each(fns, *args, **kw):
return [ fn(*args, **kw) for fn in fns ]

although this changes slightly how you call it.

I don't have any experience working with *args, **kw arguments. From
what I've read, *args allows for an unknown number of arguments to
passed into a function and **kw allows for an unknown number of
key-value pairs to passed into a function. But from what I understand,
both are optional. This shouldn't change the how you call apply_each.
[args]*len(fns) is equivalent to [args, args, args, ...] where args is repeated as often as there are elements in the list. It means that every time apply is called it gets one of the functions and the args value as its parameters.


I understand now. [args] can be a list of variables, including a list
of lists. Each variable within [args] is passed to the function called
within apply_each().

Jul 18 '05 #3

P: n/a
> I don't have any experience working with *args, **kw arguments.
From what I've read, *args allows for an unknown number of
arguments to passed into a function and **kw allows for an
unknown number of key-value pairs to passed into a function.
But from what I understand, both are optional. This shouldn't
change the how you call apply_each.


I spoke too soon. If the function being called doesn't provide for
*args, or **kw then a TypeError exception will be thrown.

Jul 18 '05 #4

P: n/a
wrote:
I don't have any experience working with *args, **kw arguments.
From what I've read, *args allows for an unknown number of
arguments to passed into a function and **kw allows for an
unknown number of key-value pairs to passed into a function.
But from what I understand, both are optional. This shouldn't
change the how you call apply_each.


I spoke too soon. If the function being called doesn't provide for
*args, or **kw then a TypeError exception will be thrown.


The original apply_each expected you to use it something like this:

def fn1(a,b,c): ... whatever ...
def fn2(a,b,c): ... whatever ...

result = apply_each([fn1, fn2], [1, 2, 3])

A revised version:

def apply_each(fns, *args, **kw):
return [ fn(*args, **kw) for fn in fns ]

could be called in a variety of ways:

result = apply_each([fn1, fn2], 1, 2, 3)
result = apply_each([fn1, fn2], *[1, 2, 3])
result = apply_each([fn1, fn2], a=1, c=3, b=2)
result = apply_each([fn1, fn2], **{'a': 1, 'c': 3, 'b': 2})

The functions actually being called don't need to know anything about how
they are invoked, they just need to get a suitable combination of
positional and/or keyword arguments.
Jul 18 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.