substituting list comprehensions for map()

J

J Kenneth King

Ben Finney said:
Strange to say it's a solution, when it doesn't solve the stated
problem: to replace use of ‘map()’ with a list comprehension.

Granted I admit this later in my post. It's not a solution to the OPs
request, but it is the best solution to such a case.
I disagree; a list comprehension is often clearer than use of ‘map()’
with a lambda form, and I find it to be so in this case.

The use of map expresses a value and implies the procedure by which it
is obtained.

The list comprehension expresses the procedure by which the value is
obtained.

Both have uses and in some cases a list comprehension is definitely
preferrable to a map operation.

However in this case the procedure by which we derive the value is not
important or even interesting. It is much more succinct to think of the
operation as a value and express it accordingly. There's no need to
clutter the mind with extra name bindings and iteration keywords. They
won't make our idea any more clear.

dot_product = map(mul, vec1, vec2)

vs

dot_product = [a * b for a, b in zip(vec1, vec2)]

It's very clear, at least to me, what a dot-product is in this case.
Adding in the loop construct and name bindings doesn't enhance my
understanding of what a dot-product is. I don't need to see the loop
construct at all in this case. A dot product is simply the
multiplication of each element in a vector sequence. It's more succinct
to simply think of the value rather then expressing the procedure to
construct that value.

This isn't a hammer issue. Not every problem is a nail.
 
S

Steven D'Aprano

However in this case the procedure by which we derive the value is not
important or even interesting. It is much more succinct to think of the
operation as a value and express it accordingly. There's no need to
clutter the mind with extra name bindings and iteration keywords. They
won't make our idea any more clear.

dot_product = map(mul, vec1, vec2)

vs

dot_product = [a * b for a, b in zip(vec1, vec2)]

It's very clear, at least to me, what a dot-product is in this case.

Except it's not.

The dot product of two vectors returns a scalar, not another vector:
http://en.wikipedia.org/wiki/Dot_product

So what you want is:

dot_product = sum(map(mul, vec1, vec2))


Adding in the loop construct and name bindings doesn't enhance my
understanding of what a dot-product is. I don't need to see the loop
construct at all in this case. A dot product is simply the
multiplication of each element in a vector sequence.

What you need is to define a function dot-product, and not hijack the
name for a local value. Then the function's implementation is irrelevant
to you: it could use a list comp, or could use map, it could use a for-
loop, a while loop, recursion, or black magic:

scalar = dot_product(vec1, vec2)
 
R

Robert Kern

Steven said:
What you need is to define a function dot-product, and not hijack the
name for a local value. Then the function's implementation is irrelevant
to you: it could use a list comp, or could use map, it could use a for-
loop, a while loop, recursion, or black magic:

scalar = dot_product(vec1, vec2)

Or use the appropriate libraries:

from numpy import dot

scalar = dot(vec1, vec2)

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco
 
S

Steven D'Aprano

Or use the appropriate libraries:

from numpy import dot

scalar = dot(vec1, vec2)


Why would I want to use an already existing library that is fast, well-
written and well-supported, when I can toss together a nasty kludge
myself?
 
T

Tim Chase

Steven said:
Why would I want to use an already existing library that is fast, well-
written and well-supported, when I can toss together a nasty kludge
myself?

because you want to perform a dot-product on strings?
>>> dot_product(['a', 'b', 'c'], [2,3,4])
'aabbbcccc'

[grins, ducks and scampers away after the
sum-shouldn't-special-case-strings-with-an-error thread]

-tkc
 
D

Dotan Cohen

My personal preference would be a link in each sub-paragraph in the official
documentation to a wiki page devoted to that specific aspect of the Python
language. A place were users could augment the documentation by providing
sample code and by expanding out the documentation for those of us who don't
live and breath Python in our sleep. Real Python coders would not click on
the user wiki links and all of us newbies could communicate with each other.
But until a place like that exists, perhaps Pyfora will get us part way
there.

The PHP documentation has this feature: user comments right on the
same page (no link to a wiki, though). It's great, most of the best
usage practices that I have learned in that language came from the
user's comments, not from the official documentation itself.
 
J

J Kenneth King

Steven D'Aprano said:
However in this case the procedure by which we derive the value is not
important or even interesting. It is much more succinct to think of the
operation as a value and express it accordingly. There's no need to
clutter the mind with extra name bindings and iteration keywords. They
won't make our idea any more clear.

dot_product = map(mul, vec1, vec2)

vs

dot_product = [a * b for a, b in zip(vec1, vec2)]

It's very clear, at least to me, what a dot-product is in this case.

Except it's not.

The dot product of two vectors returns a scalar, not another vector:
http://en.wikipedia.org/wiki/Dot_product

So what you want is:

dot_product = sum(map(mul, vec1, vec2))

Derh. Thanks for the catch. My bad.
What you need is to define a function dot-product, and not hijack the
name for a local value. Then the function's implementation is irrelevant
to you: it could use a list comp, or could use map, it could use a for-
loop, a while loop, recursion, or black magic:

scalar = dot_product(vec1, vec2)

Even better.

But now I'm afraid the example is running away from the point.

So to summarize:

1. Extra name bindings and loop keywords aren't always easier to read.

2. Expressing what we want rather than how we get it is much more clear.

and (third dirty argument added)

3. List comprehensions leak their name bindings to the surrounding
scope. :p

Have a nice day. :)
 
S

Steven D'Aprano

Because using that library will ensure you can't migrate to Python 3 any
time soon?


Why would I want to migrate to Python 3 any time soon? 2.5 and 2.6 meet
my needs (so far), and the new features in Python 3 aren't especially
compelling to me. Particularly if migrating to 3 requires me to re-write
all the libraries, where's the advantage?
 
S

Steven D'Aprano

Sounds like you've answered the questions posed, then. Good for you!

I was actually only being *half* tongue in cheek, which is why I left out
the smiley.

On the python-dev list at the moment is a lot of discussion on why uptake
of Python 3.1 has been slower than hoped. But one of the things that
people haven't really discussed -- or at least that I haven't seen -- is
why one would prefer 3.1 over 2.5 or 2.6.

I've played around with 3.0, and I've read the What's New for 3.1 (and am
installing 3.1 now), and while the changes look nice, I'm not sure that
they're nice enough to deal with the pain of 2to3 migration.

So how about that, 3.1 fans? What are the most compelling reasons for you
that convinced you to change?
 
A

Alf P. Steinbach

* Steven D'Aprano:
I was actually only being *half* tongue in cheek, which is why I left out
the smiley.

On the python-dev list at the moment is a lot of discussion on why uptake
of Python 3.1 has been slower than hoped. But one of the things that
people haven't really discussed -- or at least that I haven't seen -- is
why one would prefer 3.1 over 2.5 or 2.6.

I've played around with 3.0, and I've read the What's New for 3.1 (and am
installing 3.1 now), and while the changes look nice, I'm not sure that
they're nice enough to deal with the pain of 2to3 migration.

So how about that, 3.1 fans? What are the most compelling reasons for you
that convinced you to change?

Since I'm just learning Python and am an utter Python novice this might not
amount to much, but it's in the nature of language evolution that the new more
or less incompatible version *does* become the dominant one, and for new things
it's then a good idea to adopt the coming in future generally used version of
the language, instead of being left in a quagmire trying to catch up with new
versions of tools and libs suddenly not so compatible with the old code.

This happened with e.g. C++ standardization in 1998. The whole standard library
was revamped and put in a namespace, and old headers like [iostream.h] were
removed. And as with the Python "/" operator core language functionality was
changed: in C++98 'new' suddenly threw (Pythoneese raised) an exception instead
of returning 0 on failure, and templates were suddenly "two phase" with quite
different semantics, so that much old code didn't even compile, and when it did,
didn't work correctly.

But those who chose to stay behind paid and still for some pay the price, having
to use ages old tools and libs. One amusing or sad (depending one's point of
view) variant was where firms chose to get along with the language evolution,
tools etc., but still restrict themselves to not only pre-standard C++ but some
early 1980's version, not much more than "C with classes" or "better C". For
example, at Google they generally don't use C++ exceptions, presumably because
they have a large code base of non-exception-safe code. Still, assuming that's
the rationale, it would surprise me if they don't use exceptions in their new code.

This is perhaps an heretical view, that the new language version's advantages
don't matter so much as the fact that the new language version is incompatible,
viewing that incompatibility as a /reason/ to change.

But I think it's realistic; getting the advantages (such as with Python 3.x
improved efficiency for range etc., and thus also more clear notation) is just
an added bonus.


Cheers & hth.,

- Alf
 
M

Mensanator

I was actually only being *half* tongue in cheek, which is why I left out
the smiley.

On the python-dev list at the moment is a lot of discussion on why uptake
of Python 3.1 has been slower than hoped. But one of the things that
people haven't really discussed -- or at least that I haven't seen -- is
why one would prefer 3.1 over 2.5 or 2.6.

I've played around with 3.0, and I've read the What's New for 3.1 (and am
installing 3.1 now), and while the changes look nice, I'm not sure that
they're nice enough to deal with the pain of 2to3 migration.

So how about that, 3.1 fans? What are the most compelling reasons for you
that convinced you to change?

Itertools is worth the price of admission. As far as the "pain of
migration"
is concerned, less annoying than a mosquito bite.
 
E

Ethan Furman

Steven said:
I was actually only being *half* tongue in cheek, which is why I left out
the smiley.

On the python-dev list at the moment is a lot of discussion on why uptake
of Python 3.1 has been slower than hoped. But one of the things that
people haven't really discussed -- or at least that I haven't seen -- is
why one would prefer 3.1 over 2.5 or 2.6.

I've played around with 3.0, and I've read the What's New for 3.1 (and am
installing 3.1 now), and while the changes look nice, I'm not sure that
they're nice enough to deal with the pain of 2to3 migration.

So how about that, 3.1 fans? What are the most compelling reasons for you
that convinced you to change?

Python 3 is more pythonic. ;-)

Cleaner, more consistent, etc.

~Ethan~
 
T

Terry Reedy

Steven said:
I've played around with 3.0, and I've read the What's New for 3.1 (and am
installing 3.1 now), and while the changes look nice, I'm not sure that
they're nice enough to deal with the pain of 2to3 migration.

I am in a different position since I did not have current code that
would need migrating.
So how about that, 3.1 fans? What are the most compelling reasons for you
that convinced you to change?

I am writing a book on algorithms that uses a subset of 3.1 as the
algorithm language. It it simply cleaner and easier to explain to people
not already familiar with the quirks of 2.x. One small but
important-to-me example. I do not need to put 'from __future__ import
integerdivision' (or whatever the incantation is) as the top of files.
Hence I do not need to waste energy (mime and readers) explaining
furture imports and the specifics of the old versus new meaning of int/int.

While I initially resisted the text==unicode change, I now see it as
essential to the future of Python as a world algorithm language.

I admit that I am more bothered about the leftover quirks (to me --
sludge) in 2.x than most.

Unless you are the author/maintainer of an essential library, I have no
opinion as to what you do with old code, or even what you use for new code.

I do care about people trying to disparage or sabotage 3.x.

Terry Jan Reedy
 
G

geremy condra

I am in a different position since I did not have current code that would
need migrating.


I am writing a book on algorithms that uses a subset of 3.1 as the algorithm
language. It it simply cleaner and easier to explain to people not already
familiar with the quirks of 2.x. One small but important-to-me example. I do
not need to put 'from __future__ import integerdivision' (or whatever the
incantation is) as the top of files. Hence I do not need to waste energy
(mime and readers) explaining furture imports and the specifics of the old
versus new meaning of int/int.

I agree. Most of my code is primarily mathematical, and while I personally
see the move away from functional programming techniques as a minor
misstep, the cleanliness of it all more than makes up for that.

Geremy Condra
 

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
474,181
Messages
2,570,970
Members
47,537
Latest member
BellCorone

Latest Threads

Top