inverse of izip

Peter Otten __peter__ at web.de
Thu Aug 19 20:55:45 CEST 2004


Steven Bethard wrote:

> Peter Otten <__peter__ at web.de> wrote in message
> news:<cg1pct$p58$00$1 at news.t-online.com>...
>> However, your sample data is badly chosen. Unless I have made a typo
>> repeating your demo, you are getting the same (last) sequence twice due
>> to late binding of i.
>> 
> [snip]
>> >>> map(list, starzip(it.izip("123", "abc")))
>>  [['1', '2', '3'], ['a', 'b', 'c']]
>> >>> x, y = starzip(it.izip("123", "abc"))
>> >>> list(x)
>>  ['a', 'b', 'c']
>> >>> list(y)
>>  ['a', 'b', 'c']
>> >>>
> 
> I knew there was something funny about binding in generators, but I
> couldn't remember what...  Could you explain why 'map(list, ...)'
> works, but 'x, y = ...' doesn't?  I read the PEP, but I'm still not
> clear on this point.

Maybe the following example can illustrate what I think is going on:

import itertools as it

def starzip(iterables):
    return ((t[i] for t in itr)
       for (i, itr) in
       enumerate(it.tee(iterables)))

# the order of calls equivalent to map(list, starzip(...))
s = starzip(it.izip("abc", "123"))
x = s.next() 
# the local variable i in starzip() shared by x and y
# is now 0 
print x.next(),
print x.next(),
print x.next()
y = s.next() 
# i is now 1, but because no further calls to x.next()
# will occur it doesn't matter
print y.next(),
print y.next(),
print y.next()

s = starzip(it.izip("abc", "123"))
x = s.next() # i is 0
y = s.next() # i is 1
# both x an y yield t[1]
print x.next(),
print x.next(),
print x.next()

print y.next(),
print y.next(),
print y.next()

You can model the nested generator expressions' behaviour with the following
function - which I think is much clearer. 

def starzip(iterables):
    def inner(itr):
        for t in itr:
            yield t[i]

    for (i, itr) in enumerate(it.tee(iterables)):
        yield inner(itr)

Note how itr is passed explicitly, i. e. it is not affected by later
rebindings in startzip() whereas i is looked up in inner()'s surrounding
namespace at every yield.

Peter




More information about the Python-list mailing list