The Occasional Occurence
Python's Enhanced Generators
June 13, 2008 at 01:38 PM | categories: Python, computing, GeneralSo while I was mowing my grass last night*, I got to thinking about Python 2.5's enhanced generators and how I hadn't tried them out yet. Here is a simple example that uses the consumer/pipeline model described in PEP 342.
__author__ = "Christian Wyglendowski"
__license__ = "MIT"
def consumer(func):
"""Automatically advance generator to 1st yield point - (from PEP 342)"""
def wrapper(*args, **kw):
gen = func(*args, **kw)
gen.next()
return gen
wrapper.__name__ = func.__name__
wrapper.__dict__ = func.__dict__
wrapper.__doc__ = func.__doc__
return wrapper
@consumer
def reverser(next=None):
"""A string-reversing consumer"""
t = yield
if next:
yield next.send("".join(reversed(t)))
else:
yield "".join(reversed(t))
def transformer(methodname, *args, **params):
"""Creates a consumer for the given string methodname.
Passes *args and **params to the string method."""
@consumer
def _transform(next=None):
text = yield
m = getattr(text, methodname)
transformed = m(*args, **params)
if next:
yield next.send(transformed)
else:
yield transformed
_transform.__name__ = methodname
return _transform
def transform(text, transformers):
"""Passes text through a list of transformers and returns the result."""
next = None
for t in reversed(transformers):
next = t(next)
return next.send(text)
(Is this too much code for a blog post?)
So what can you do with all of that? Easily perform various combinations of string transformations!
In [1]: title = transformer('title')
In [2]: transform('python', [title, reverser])
Out[2]: 'nohtyP'
In [3]: transform('python', [reverser, title])
Out[3]: 'Nohtyp'
It's a fairly contrived example, but the concept of this pipeline of transformations (described in much more detail in PEP 342) is really pretty cool. An application applying a more advanced version of something like this could process it's output using a variety of plugins that a user enabled.
Here is one final example:
In [4]: decode = transformer('decode', 'utf-8')
In [5]: replace = transformer('replace', unichr(347), 's')
In [6]: encode = transformer('encode', 'utf-8')
In [7]: transform('Chri\xc5\x9btian', [decode, replace, encode])
Out[7]: 'Christian'
Has anyone else seen any neat examples of PEP 342 in the wild?
cw
* I usually gravitate to thinking about some obscure programming paradigm or feature while I am mowing grass. I think it has to do with how exceptionally boring mowing is.
EDIT: I guess I could have made the generators, um, more generative, so they aren't simply one-shot function-like simpletons. Oh well.