map

E

elsa

Hi,

i have a question about the built in map function. Here 'tis:

say I have a list, myList. Now say I have a function with more than
one argument:

myFunc(a, b='None')

now, say I want to map myFunc onto myList, with always the same
argument for b, but iterating over a:

map(myFunc(b='booHoo'), myList)

Why doesn't this work? is there a way to make it work?

(Ultimately, I want to call myFunc(myList[0], 'booHoo'), myFunc(myList
[1], 'booHoo'), myFunc(myList[2], 'booHoo') etc. However, I might want
to call myFunc(myList[0], 'woo'), myFunc(myList[1], 'woo'), myFunc
(myList[2], 'woo') some other time).

Thanks,

Elsa
 
C

Chris Rebert

Hi,

i have a question about the built in map function. Here 'tis:

say I have a list, myList. Now say I have a function with more than
one argument:

myFunc(a, b='None')

now, say I want to map myFunc onto myList, with always the same
argument for b, but iterating over a:

map(myFunc(b='booHoo'), myList)

Why doesn't this work?

Because myFunc is executed before map() is ever called, and you didn't
specify a value for the `a` parameter, hence you get an error about
not giving a value for `a`.
Another way of saying this: Python uses "eager evaluation"
(http://en.wikipedia.org/wiki/Eager_evaluation) most of the time.
is there a way to make it work?

Use functools.partial to fill in the `b` parameter:
http://docs.python.org/library/functools.html#functools.partial

#untested example:
from functools import partial
f = partial(myFunc, b='booHoo')
map(f, myList)

Cheers,
Chris
 
R

rurpy

i have a question about the built in map function. Here 'tis:

say I have a list, myList. Now say I have a function with more than
one argument:

myFunc(a, b='None')

now, say I want to map myFunc onto myList, with always the same
argument for b, but iterating over a:

map(myFunc(b='booHoo'), myList)

Why doesn't this work? is there a way to make it work?

When you write "map(myFunc(b='booHoo'), myList)", you are telling
Python to call myFunc before the map function is called, because
an argument list, "(b='booHoo')", follows myFunc. You want
to pass map a function object, not the results of calling a
function object.

A couple ways to do what you want:

map(lambda a: myFunc(a, b='booHoo'), myList)

The lamba expression creates a new function of one argument
(which is needed by map) that, when executed, will call myFunc
with the two arguments it needs.

You can also just define an ordinary function that does
the same thing as the lambda above:

def tmpFunc (a)
myFunc (a, b='booHoo')
...
map (tmpFunc, myList)

In the functools module there is a function called "partial"
that does something similar to the lambda above. I'll leave
it to you you look it up if interested.

HTH
 
H

Hendrik van Rooyen

On Monday 31 August 2009 06:55:52 elsa wrote:

8< --------- map question ----------------------------
(Ultimately, I want to call myFunc(myList[0], 'booHoo'), myFunc(myList
[1], 'booHoo'), myFunc(myList[2], 'booHoo') etc. However, I might want
to call myFunc(myList[0], 'woo'), myFunc(myList[1], 'woo'), myFunc
(myList[2], 'woo') some other time).

Here is some heretical advice:

Do not use stuff like map and reduce unless they fit what you want to do
perfectly, and "JustWorks" the first time.

You have a very clear idea of what you want to do, so why do you not just
simply write something to do it?

something like this (untested):

def woofer(thefunc,thelist,thething):
theanswers = []
for x in thelist:
theanswers.append(thefunc(x,thething))
return theanswers

And the advantage is that you do not have to remember what map does...

*ducks away from the inevitable flames*

- Hendrik
 
G

Gabriel Genellina

En Mon, 31 Aug 2009 05:43:07 -0300, Hendrik van Rooyen
(Ultimately, I want to call myFunc(myList[0], 'booHoo'), myFunc(myList
[1], 'booHoo'), myFunc(myList[2], 'booHoo') etc. However, I might want
to call myFunc(myList[0], 'woo'), myFunc(myList[1], 'woo'), myFunc
(myList[2], 'woo') some other time).

Here is some heretical advice:

Do not use stuff like map and reduce unless they fit what you want to do
perfectly, and "JustWorks" the first time.

I think of that advice as "orthodox", not "heretical"! (functional guys
are minority here...)
You have a very clear idea of what you want to do, so why do you not just
simply write something to do it?

something like this (untested):

def woofer(thefunc,thelist,thething):
theanswers = []
for x in thelist:
theanswers.append(thefunc(x,thething))
return theanswers

And the advantage is that you do not have to remember what map does...

This block:

theanswers = []
for x in thelist:
theanswers.append(thefunc(x,thething))

is formally the same as this one:

theanswers = [thefunc(x,thething) for x in thelist]

but the list comprehension is faster. So the function becomes:

def woofer(thefunc,thelist,thething):
return [thefunc(x,thething) for x in thelist]

and may be inlined (it's usually easier to read).
*ducks away from the inevitable flames*

*fights back to back with you against heretics*
 
P

Piet van Oostrum

Hendrik van Rooyen said:
HvR> On Monday 31 August 2009 06:55:52 elsa wrote:
HvR> 8< --------- map question ----------------------------
(Ultimately, I want to call myFunc(myList[0], 'booHoo'), myFunc(myList
[1], 'booHoo'), myFunc(myList[2], 'booHoo') etc. However, I might want
to call myFunc(myList[0], 'woo'), myFunc(myList[1], 'woo'), myFunc
(myList[2], 'woo') some other time).
HvR> Here is some heretical advice:
HvR> Do not use stuff like map and reduce unless they fit what you want to do
HvR> perfectly, and "JustWorks" the first time.
HvR> You have a very clear idea of what you want to do, so why do you not just
HvR> simply write something to do it?
HvR> something like this (untested):
HvR> def woofer(thefunc,thelist,thething):
HvR> theanswers = []
HvR> for x in thelist:
HvR> theanswers.append(thefunc(x,thething))
HvR> return theanswers
HvR> And the advantage is that you do not have to remember what map does...

Map should be in every good programmer's toolbox. So (s)he presumably
knows already what map does. In order to follow your advise (s)he must
first forget what map does :=)

Agreed on the part that map shouldn't be used indiscriminately. Neither
should loops. Your woofer is much harder to follow than map, I think.

[myFunc(elt, 'booHoo') for elt in myList] is also a good candidate and
in this case I think it is preferable to both the loop and the map with
a partial or lambda in terms of clarity.

On the other hand when you just want to call a function on each element
of a list and you don't need to collect the result a simple loop is
often preferable.

But ultimately it is also very much a matter of taste, preference and habit.
 
S

Steven D'Aprano

Here is some heretical advice:

Do not use stuff like map and reduce unless they fit what you want to do
perfectly, and "JustWorks" the first time.

You have a very clear idea of what you want to do, so why do you not
just simply write something to do it?

That's not heretical advice -- that's pretty standard, vanilla, boring
advice. It's probably good advice, if you care more about Getting the Job
Done than about learning the language.

And the advantage is that you do not have to remember what map does...

map() is probably the simplest, most straightforward of the functional
tools in Python. It's harder for me to remember it's name than to
remember what it does: it applies a function to each element of a list,
instead of two the entire list as a single argument. Easy-peasy.
*ducks away from the inevitable flames*

You'll have to try harder than that to get flamed :)
 
H

Hendrik van Rooyen

But ultimately it is also very much a matter of taste, preference and
habit.

This is true, but there is another reason that I posted - I have noticed that
there seems to be a tendency amongst newcomers to the group to go to great
lengths to find something that will do exactly what they want, irrespective
of the inherent complexity or lack thereof of that which they are trying to
do.

Now I cannot understand why this is - one could say that it is caused by an
eagerness to understand all the corners of the tool that is python, but
somehow it does not feel like that to me - I see it almost as a crisis of
confidence - as if the newbie lacks the self confidence to believe that he or
she is capable of doing anything independently.

So whenever I can, I try to encourage people to just do it their way, and to
see what happens, and to hack using the interactive interpreter, to build
confidence by experimenting and making mistakes, and realizing that when you
have made a mistake, it is not the end of the world, - you can fix it and
move on.

Don't know if this rant makes any sense...

- Hendrik
 
P

Paul Rubin

elsa said:
map(myFunc(b='booHoo'), myList)

Why doesn't this work? is there a way to make it work?

You can use functools.partial but a listcomp might be simpler:

list(myfunc(a, b='booHoo') for a in myList)

There is another listcomp syntax with square brackets, but I try to
avoid it because it has broken behavior (leaks the index variable) in
Python 2.x.
 
J

Jan Kaliszewski

Another possibilities, if you really *desire* to use map()
and not list-comprehension (I'd prefer the latter), are:

# Python 2.x:
map(func, mylist, itertools.repeat('booHoo', len(mylist)))

# Python 3.x, where map() works like Py2.x's itertools.imap():
list(map(func, mylist, itertools.repeat('booHoo')))

Cheers,
*j
 
N

Nobody

say I have a list, myList. Now say I have a function with more than
one argument:

myFunc(a, b='None')

now, say I want to map myFunc onto myList, with always the same
argument for b, but iterating over a:

map(myFunc(b='booHoo'), myList)

Why doesn't this work?

You're passing the result of (incorrectly) calling myFunc to map(), but
you need to pass a function.
is there a way to make it work?

If you need to construct a simple function on-the-fly, you can use a
lambda form:

map(lambda x: myFunc(x, b='booHoo'), myList)

Or you could use a list comprehension:

[myFunc(x, b='booHoo') for x in myList]
 
E

elsa

This is true, but there is another reason that I posted - I have noticed that
there seems to be a tendency amongst newcomers to the group to go to great
lengths to find something that will do exactly what they want, irrespective
of the inherent complexity or lack thereof of that which they are trying to
do.

Now I cannot understand why this is - one could say that it is caused by an
eagerness to understand all the corners of the tool that is python, but
somehow it does not feel like that to me - I see it almost as a crisis of
confidence - as if the newbie lacks the self confidence to believe that he or
she is capable of doing anything independently.  

So whenever I can, I try to encourage people to just do it their way, and to
see what happens, and to hack using the interactive interpreter, to build
confidence by experimenting and making mistakes, and realizing that when you
have made a mistake, it is not the end of the world,  - you can fix it and
move on.

Don't know if this rant makes any sense...

- Hendrik

in my own defense - firstly, I was able to implement what I wanted to
do with loops, and I used this to solve the problem I needed to.

However, by asking *why* map didn't work, I now understand how map
works, what contexts it may indeed be useful for, and what the
alternatives are. To boot, you have all given me about 10 different
ways of solving the problem, some of which use prettier (and probably
faster) code than the loops I wrote...
 
H

Hendrik van Rooyen

in my own defense - firstly, I was able to implement what I wanted to
do with loops, and I used this to solve the problem I needed to.

My rant was not intended as a personal attack - far from it - if all the
people on this list were to post such clear questions as you did, it would be
an even greater pleasure to participate in than it is.
However, by asking *why* map didn't work, I now understand how map
works, what contexts it may indeed be useful for, and what the
alternatives are. To boot, you have all given me about 10 different
ways of solving the problem, some of which use prettier (and probably
faster) code than the loops I wrote...

Good. So you will soon be here answering questions too. When you do that, you
really learn, as long as you do not feel slighted when people point out
better (or merely different) solutions than yours. We all help each other
here, and sometimes we even crack obscure (and not so obscure) jokes.

- Hendrik
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top