Dangerous behavior of list(generator)

Tom Machinski tom.machinski at gmail.com
Sat Dec 12 19:15:23 EST 2009


In most cases, `list(generator)` works as expected. Thus,
`list(<generator expression>)` is generally equivalent to `[<generator
expression>]`.

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



More information about the Python-list mailing list