[Python-3000] map() Returns Iterator
Guido van Rossum
guido at python.org
Tue Aug 7 04:22:40 CEST 2007
On 8/6/07, Kurt B. Kaiser <kbk at shore.net> wrote:
> "Guido van Rossum" <guido at python.org> writes:
[...pushback...]
> However, IMHO eliminating the strict versions of map() and filter() in
> favor of the lazy versions from itertools kicks the degree of
> sophistication necessary to understand these functions up a notch (or
> three).
I wonder how bad this is given that range() and dict.keys() and
friends will also stop returning lists? I don't think you ever saw any
of my Py3k presentations (the slides of the latest one at here:
http://conferences.oreillynet.com/presentations/os2007/os_vanrossum.ppt).
I've always made a point of suggesting that we're switching to
returning iterators instead of lists from as many APIs as makes sense
(I stop at str.split() though, as I can't think of a use case where
the list would be so big as to be bothersome).
> To say nothing of remembering having to use
>
> 3>> foo = (list(map(bar)))
>
> most the time.
I think you're overreacting due to your experience with conversion of
existing code. I expect that new use cases where a list is needed will
generally be written using list comprehensions in Py3k-specific
tutorials, and generator expressions for situations where a list isn't
needed (as a slightly more advanced feature). Then map() and filter()
can be shown as more advanced optimizations of certain end cases.
> I'd say keep map(), filter(), imap() and ifilter(), and
> use the latter when you're working with streams.
>
> "Explicit is better than implicit."
>
> Then there's the silent failure to process the side-effects of
>
> 3>> map(print, lines)
>
> which is rather unexpected. To me, this code is quite readable and not
> at all pathological (no more than any print statement :). It may not be
> Pythonic in the modern idiom (that pattern is found mostly in code.py
> and IDLE, and it's very rare), but it's legal and it's a little
> surprising that it's necessary to spell it
>
> 3>> list(map(print, lines))
>
> now to get any action.
Aren't you a little too fond of this idiom? I've always found it a
little surprising when I encountered it, and replaced it with the more
straightforward
for line in lines:
print(line)
> It took me awhile to track down the failures in
> the interactive interpreter emulator because that pattern was being used
> to print the exceptions; the thing just produced no output at all.
I think that's just a side effect of the conversion. I take it you
didn't use 2to3?
> The alternatives
>
> 3>> print('\n'.join(lines))
>
> or
>
> 3>> (print(line) for line in lines) # oops, nothing happened
> 3>> [print(line) for line in lines]
>
> aren't much of an improvement.
Well duh. Really. What's wrong with writing it as a plain old for-loop?
> >> In existing Lib/ code, it's twice as likely that the result of map()
> >> will be assigned than to use it as an iterator in a flow control
> >> statement.
> >
> > Did you take into account the number of calls to imap()?
>
> No. Since the py3k branch is partially converted, I went back to 2.6,
> where skipping Lib/test/, there are (approximately!!):
>
> 87 assignments of the output of map(), passing a list
> 21 assignments involving map(), but not directly. Many of these involve
> 'tuple' or 'join' and could accept an iterator.
> 58 return statements involving map() (39 directly)
> 1 use to construct a list used as an argument
> 2 for ... in map() (!!) and 1 for ... in enumerate(map(...))
> 1 use as map(foo, bar) == baz_list
> 5 uses of imap()
I'm not sure what the relevant of assignments is. I can assign an
iterator to a variable and do stuff with it and never require it to be
a list. I can also pass a map() call into a function and then it
depends on what the function does to that argument.
> [...]
>
> > We didn't write the 2to3 transform, but it's easier than some others
> > we already did (e.g. keys()).
>
> I see a transform in svn.
I guess I didn't look well enough.
> As an aside, is there any accepted process
> for running these transforms over the p3yk branch? Some parts of Lib/
> are converted, possibly by hand, possibly by 2to3, and other parts are
> not.
(Aside: Please skip the p3yk branch and use the py3k-struni branch --
it's the way of the future.)
I tend to do manual conversion of the stdlib because it's on the
bleeding edge. At times I've regretted this, and gone back and run a
particular transform over some of the code. I rarely use the full set
of transforms on a whole subtree, although others sometimes do that.
Do note the options that help convert doctests and deal with print()
already being a function.
[zip()]
> It's used only fifteen times in 2.6 Lib/ and four of those are
> izip(). Eight are assignments, mostly to build dicts.
I don't understand. What's an "assignment" to build a dict? Do you
mean something like
dict(zip(keys, values))
? That's an ideal use case for an iterator.
--
--Guido van Rossum (home page: http://www.python.org/~guido/)
More information about the Python-3000
mailing list