[Python-3000] Iterators for dict keys, values, and items == annoying :)
Ian Bicking
ianb at colorstudy.com
Fri Mar 24 04:24:12 CET 2006
Guido van Rossum wrote:
> On 3/23/06, Ian Bicking <ianb at colorstudy.com> wrote:
>> Guido van Rossum wrote:
>>> But this is only needed if *all you have* is the iterator. Most of the
>>> time, the code containing the for loop has access to the container,
>>> and the iterator is only instantiated by the __iter__() call implied
>>> by the for loop.
>> I don't think that is the case. For instance:
>>
>> def non_empty_lines(seq):
>> for line in seq:
>> if line.strip() and not line.strip().startswith('#'):
>> yield line
>>
>> for line in non_empty_lines(open('config.txt')):
>> ...
>>
>> I think wrapping the iterator in non_empty_lines() shouldn't cause you
>> to have to rewrite your logic to radically.
>
> Radically compared to what?
Starts out:
if os.stat(filename).st_size: # weird, but your suggestion ;)
with open(filename) as lines:
for line in lines:
read_config(line)
else:
get_default_config()
Adding comments and empty line handling, the code becomes:
with open(filename) as lines:
empty = True
for line in non_empty_lines(lines):
empty = False
read_config(line)
if empty:
get_default_config()
To me that feels like a big transformation, where I would prefer to just
be able to use "non_empty_lines(lines)" in place of "lines" and
everything would work perfectly. If I started out with the second
example instead of the first, it *would* work perfectly. But I don't do
so. If that second example looked just a little nicer I would use that
form, and then there wouldn't be any problem. It really doesn't matter
for this case if the test comes before (using __nonzero__) or after the
for loop (using a did-that-loop-run flag).
Of course, no syntax comes to mind to improve this. Repurposing the
else clause in for loops seems like it just adds to the confusing of an
already confusing construct. If you could somehow count how many times
the loop had run, that'd work great; but I don't see any way to do that
without new syntax.
>> More generally, I find
>> myself using list() fairly often lately as generators have become more
>> popular, and it's not just with SQLObject. Testing for the existence of
>> any items in the iterator (is that a better way of saying it than
>> empty?) is often the reason.
>
> If creating a copy of all items using list() is not a problem, then
> you shouldn't have been using iterators in the first place. Iterators
> exist so you can efficiently handle cases where list() would overflow
> memory. If you don't have such cases, you should just design your APIs
> to return lists in the first place.
You've just made the argument that dict.keys() should return a list ;)
Or a view would work just as well, I suppose. Maybe you've just made
the argument that it should return an iterable, not an iterator.
--
Ian Bicking | ianb at colorstudy.com | http://blog.ianbicking.org
More information about the Python-3000
mailing list