Variable length "yield"?

I would like to have yield variable number of elements that would allow me to write a generator function of the following type:

 x = [1, 2, 3] y = [4, 5, 6] z = [7, 8, 9] def multi_enumerate(*iterables): n = 0 iterators = map(iter, iterables) while iterators: yield n, *tuple(map(next, iterators)) # invalid syntax n += 1 for i,a,b,c in multi_enumerate(x, y, z): print i,a,b,c 

Does anyone know how to do this? I know that I can get a tuple, but for this I need to explicitly unpack it on the receiving side, for example: a,b,c = t[0], t[1], t[2] .

Final decision :

FWIW, this is what I ended up using, based on a comment by John Kugelman:

 from itertools import izip def multi_enumerate(*iterables, **kwds): start = kwds.get('start') if start is None: if kwds: raise TypeError( "multi_enumerate() accepts only the keyword argument 'start'") try: iter(iterables[-1]) # last non-keyword arg something iterable? except TypeError: # no, assume it the start value start, iterables = iterables[-1], iterables[:-1] else: start = 0 # default return ((n,)+t for n, t in enumerate(izip(*iterables), start)) 

The added code, because of my desire to also force it to accept an optional non-iterable last argument, to indicate an initial value other than 0 (or specify it using the start keyword argument), as well as the built-in enumerate() .

+4
source share
4 answers

Change the yield to the following:

 yield (n,) + tuple(map(next, iterators)) 

Or use izip and enumerate to exclude the whole loop:

 from itertools import izip def multi_enumerate(*iterables): return ((n,) + t for n, t in enumerate(izip(*iterables))) 
+5
source

I would use chain from itertools :

 yield tuple(chain((n,), map(next, iterators))) 
+1
source

This will return an iterator that creates (n, *l[n]) for i n -length l s. It will work directly instead of your multienumerate method.

 from itertools import izip def enumerated_columns(*rows): return izip(range(len(rows[0])), *rows) 
0
source

If you want to delegate several elements from your generator to another generator, there is no one-line way to do this - if you are not using Python 3.3, that yield from function .

I will iterate over nested generators, getting values ​​from them explicitly, something like

 yield n for value in (delegated.next for delegated in iterators): yield value 
0
source

Source: https://habr.com/ru/post/1441350/


All Articles