1

I need a 2D loop of which the first loop uses an iterator and the second uses a generator, but this simple function failed to work, can anyone help to check?

def alphabet(begin, end):
    for number in xrange(ord(begin), ord(end)+1):
        yield chr(number)

def test(a, b):
    for i in a:
        for j in b:
            print i, j

test(xrange(8, 10), alphabet('A', 'C'))

The result shows:
>>> 8 A
>>> 8 B
>>> 8 c

don't know why? thanks in advance if any one can help.

2 Answers 2

2

The first iteration over b consumes the generator.

1
  • Sorry, but could you be more specific?
    – j5shi
    Commented Apr 24, 2012 at 2:25
1

Since you've asked for clarification, I'll say a bit more; but really Ignacio's answer sums it up pretty well: you can only iterate over a generator once. The code in your example tries to iterate over it three times, once for each value in a.

To see what I mean, consider this simplistic example:

>>> def mygen(x):
...     i = 0
...     while i < x:
...         yield i
...         i += 1
... 
>>> mg = mygen(4)
>>> list(mg)
[0, 1, 2, 3]
>>> list(mg)
[]

When mygen is called, it creates an object which can be iterated over exactly once. When you try to iterate over it again, you get an empty iterable.

This means you have to call mygen anew, every time you want to iterate over it`. So in other words (using a rather verbose style)...

>>> def make_n_lists(gen, gen_args, n):
...     list_of_lists = []
...     for _ in range(n):
...         list_of_lists.append(list(gen(*gen_args)))
...     return list_of_lists
... 
>>> make_n_lists(mygen, (3,), 3)
[[0, 1, 2], [0, 1, 2], [0, 1, 2]]

If you wanted to bind your arguments to your generator and pass that as an argumentless function, you could do this (using a more terse style):

>>> def make_n_lists(gen_func, n):
...     return [list(gen_func()) for _ in range(n)]
... 
>>> make_n_lists(lambda: mygen(3), 3)
[[0, 1, 2], [0, 1, 2], [0, 1, 2]]

The lambda just defines an anonymous function; the above is identical to this:

>>> def call_mygen_with_3():
...     return mygen(3)
... 
>>> make_n_lists(call_mygen_with_3, 3)
[[0, 1, 2], [0, 1, 2], [0, 1, 2]]
1
  • Thanks, your post is helpful.
    – j5shi
    Commented Apr 24, 2012 at 3:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.