I often find it cleaner to write a generator than to return a list. For example, I prefer
def my_func_gen(foo):
for i in foo:
# Do some stuff that's too complicated for a list or generator comprehension
yield whatever
to
def my_func_list(foo):
result = []
for i in foo:
# Do some stuff that's too complicated for a list or generator comprehension
result.append(whatever)
return result
Further, this answer says, "You're encouraged to use iterators for everything." So is my_func_gen
better, then? Maybe not. I'd like for the caller not to even know whether it's getting a list or an iterator. But the caller has to think about it because, for example, the iterator won't be sliceable using Python's nice clean syntax; I'll have to use itertools.islice
.
So what should I do?
- Ignore the advice to "use iterators for everything"
- Get out of the habit of using slices and other behavior that's not available to all iterables
- Run
list(my_iterable)
any time I might want to use features that lists support and generators do not - Use lists sometimes and generators others. But when?
Related: here's some code that users a wrapper class to make any iterator sliceable. It doesn't work quite the way you might think, though: looking up foo[:2]
and then looking up foo[:2]
again gives different results.