Modifying yield from's return value Modifying yield from's return value python-3.x python-3.x

Modifying yield from's return value


There is another way doing this besides try ... yield ... except: by implementing a new generator. With this class you can transform all the inputs and outputs of your underlying generator:

identity = lambda x: xclass map_generator:  def __init__(self, generator, outfn = identity,      infn = identity, throwfn = identity):    self.generator = generator    self.outfn = outfn    self.infn = infn    self.throwfn = throwfn    self.first = True  def __iter__(self):    return self  def __next__(self):    return self.send(None)  def _transform(self, value):    if self.first:      self.first = False      return value    else:      return self.infn(value)  def send(self, value):    return self.outfn(self.generator.send(self._transform(value)))  def throw(self, value):    return self.outfn(self.generator.throw(self.throwfn(value)))  def next(self): # for python2 support    return self.__next__()

Usage:

def foo():  for i in "123":    print("sent to foo: ", (yield i))def bar():  dupe = lambda x:2*x  tripe = lambda x:3*x  yield from map_generator(foo(), dupe, tripe)i = bar()print("received from bar: ", i.send(None))print("received from bar: ", i.send("B"))print("received from bar: ", i.send("C"))...received from bar:  11sent to foo:  BBBreceived from bar:  22sent to foo:  CCCreceived from bar:  33

EDIT: You might want to inherit from collections.Iterator, but it is not neccessary in this usecase.


Have parse_foo and parse_bar add the extensions:

def parse_foo(ext):    # Existing code    ...    # Add an extension to the item(s)    item.ext = extdef parse(ext):    yield from parsers[ext](ext)

Or just hardcode it in each function:

def parse_foo():    # Existing code    ...    # Add an extension to the item(s)    item.ext = ".foo"


Unfortunately there is no built-in that does it. You may implement it yourself using classes but a package called cotoolz implements a map() function that does exactly that.

Their map function is 4 times slower than the builtin map() but it's aware to the generator protocol, and faster than a similar Python implementation (it's written in C and requires a C99 compiler).

An example from their page:

>>> def my_coroutine():...     yield (yield (yield 1))>>> from cotoolz import comap>>> cm = comap(lambda a: a + 1, my_coroutine())>>> next(cm)2>>> cm.send(2)3>>> cm.send(3)4>>> cm.send(4)Traceback (most recent call last):    ...StopIteration