Dr. Phillip M. Feldman wrote: > > It is supposed to be possible to generate a list representation of any > iterator that produces a sequence of finite length, but this doesn't > always work. Here's a case where it does work: > > Input: > > from itertools import combinations > list(combinations(range(4),2)) > > Output: > > [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)] > > When I define my own classes that produce iterators, conversion to a list > works for some of these classes but not for others. Here's a case where it > doesn't work: > > In: list(balls_in_numbered_boxes(2, [3,3,3])) > > Out: > > [array([0, 0, 1]), > array([0, 0, 1]), > array([0, 0, 1]), > array([0, 0, 1]), > array([0, 0, 1])]
[snip code where excessive commenting does more bad than good] The problem is that you return the same mutable object on every next() call. Here's a simplified example: >>> def g(items): ... x = [None] ... for item in items: ... x[0] = item ... yield x ... >>> list(g("abc")) [['c'], ['c'], ['c']] When you invoke it using next() you are fooled into thinking that it works as desired: >>> it = g("abc") >>> a = next(it) >>> a ['a'] >>> b = next(it) >>> b ['b'] but only until you look back at the previous item: >>> a ['b'] Once you understand what is going on the fix is easy -- don't reuse the mutable object: >>> def g(items): ... for item in items: ... yield [item] ... >>> list(g("abc")) [['a'], ['b'], ['c']] -- http://mail.python.org/mailman/listinfo/python-list