Dangerous behavior of list(generator)

Benjamin Kaplan benjamin.kaplan at case.edu
Sun Dec 13 01:53:57 CET 2009


On Sat, Dec 12, 2009 at 7:15 PM, Tom Machinski <tom.machinski at gmail.com> wrote:
> In most cases, `list(generator)` works as expected. Thus,
> `list(<generator expression>)` is generally equivalent to `[<generator
> expression>]`.
>

Actually, it's list(generator) vs. a list comprehension. I agree that
it can be confusing, but Python considers them to be two different
constructs.

>>> list(xrange(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [xrange(10)]
[xrange(10)]



> Here's a minimal case where this equivalence breaks, causing a serious
> and hard-to-detect bug in a program:
>
>  >>> def sit(): raise StopIteration()
>  ...
>  >>> [f() for f in (lambda:1, sit, lambda:2)]
>  Traceback (most recent call last):
>    File "<stdin>", line 1, in <module>
>    File "<stdin>", line 1, in sit
>  StopIteration
>  >>> list(f() for f in (lambda:1, sit, lambda:2))
>  [1]
>
> I was bitten hard by this inconsistency when sit() was returning the
> idiom `(foo for foo in bar if foo.is_baz()).next()`. The nonexistence
> of a foo with is_baz() True in that query raises an exception as
> designed, which expresses itself when I use the list comprehension
> version of the code above; the generator version muffles the error and
> silently introduces a subtle, confusing bug: `lambda:2` is never
> reached, and a truncated list of 1 element (instead of 3) is
> "successfully" generated..
>
> Just wondered what you guys think,
>
>  -- Tom
> --
> http://mail.python.org/mailman/listinfo/python-list
>



More information about the Python-list mailing list