[Tutor] list comprehension equivalent to map(function, list item)
Steven D'Aprano
steve at pearwood.info
Sat Dec 14 04:54:42 CET 2013
On Fri, Dec 13, 2013 at 08:03:57PM -0500, Bo Morris wrote:
> i have the following simple function that iterates over the list.
Actually, no it doesn't. One important skill of being a programmer is
precision of language. The function "add" you show below does not
iterate over the list, it is the *map* function which does the
iteration.
> It passes the list item into the function and adds the numbers.
Again, not so much. When you talk about adding up the numbers, given
numbers like 5, 3, 2 I would expect to get 10 as the answer. That is not
what your function does: it adds one to *each* number, alone.
Now that I've lectured you pedantically on precision of language, which
I hope you'll take in the constructive spirit it is intended, let me
answer your actual question:
> What would be the
> equivalent way of writing the "map" portion with list comprehension? My
> code is as follows:
>
> def add(number):
> print 1 + int(number)
>
> x = ['2', '4', '6', '8', '10', '12']
> map(add, x)
Converting a map to a list comprehension is simple:
map(function, items)
becomes:
[function(item) for item in items]
So your example simply becomes [add(s) for s in list_of_strings]
A couple of other points:
(1) The more work a variable is used for, the more descriptive its name
should be. Variables which are used once can be a single letter.
Temporary variables which don't last very long also can be a single
letter. It is conventional to use a few single letter names:
i, j, k: loop variables
n, m: integers
x, y: floats or decimals
s: strings
but only when they represent generic values. If possible, you should
give variables names which explain *what they are* (such as
"list_of_strings") or even better, *what they are used for* (such as
"scores", "width", "number_of_pages", etc.)
(2) In your example, your "add" function actually does two things:
- it *calculates* a result (adding one to a number);
- it *displays* that result (print).
In general, it is best to keep those two parts separate. Why? Because
good, effective programming involves putting parts together to make
bigger parts. Once you introduce a print into a function, you can't
really combine that part into a new more powerful part. You are now
committed to *only* printing the calculation result, even if what you
actually want to do is to perform more calculations on it.
An example: suppose that, after adding one, you then want to double the
result. You might think that you could do this:
def double(number):
print 2*number
double(add(20))
That's exactly the sort of putting building blocks together that
programming is all about. But if you try it, you'll see that it doesn't
work. You'll get a mysterious error something like this:
TypeError: unsupported operand type(s) for *: 'int' and 'NoneType'
Why? Because your "add" function takes the calculated result and prints
it, then throws the result away. Since the function doesn't return a
value for later use, Python automatically returns the special None
value, which you can think of as meaning something like "nothing at
all". What happens when you try to double None? You get an error.
The way to fix this and write functions which can be used as building
blocks is to use "return" instead of "print", then call print at the
end, only when you want to actually see something:
def add(number):
return 1 + int(number)
x = ['2', '4', '6', '8', '10', '12']
print map(add, x)
def double(number):
return 2*number
print double(add(20))
If you have any questions, please don't hesitate to ask!
--
Steven
More information about the Tutor
mailing list