Simon Wittber wrote: > I use a coroutine/generator framework for simulating concurrent processes. > > To do this, I write all my functions using the general form: > > while True: > do stuff > yield None > > To make these generator functions compatible with a standard thread > interface, I attempted to write a decorator which converts a standard > function into a generator function (code attached below). > Unfortunately, I received an exception, before I could test if my idea > would work: > > TypeError: cannot create 'generator' instances > > I guess I can go the other way, and convert a generator into a > function, but that just doesn't seem right. > > Is there anyway solve the problem described? Generators are just functions with an extra flag set. I tried the following modification of your code:
<code> from opcode import opmap globals().update(opmap) def _f(): pass function = type(_f) del _f def generatorize(f): co = f.func_code nc = [ord(x) for x in co.co_code] for i, op in enumerate(nc[:-1]): if op == RETURN_VALUE: nc[i] = YIELD_VALUE newcode = ''.join([chr(x) for x in nc]) codeobj = type(co)(co.co_argcount, co.co_nlocals, co.co_stacksize, co.co_flags + 32, newcode, co.co_consts, co.co_names, co.co_varnames, co.co_filename, co.co_name, co.co_firstlineno, co.co_lnotab, co.co_freevars, co.co_cellvars) return function(codeobj, f.func_globals, f.func_name, f.func_defaults, f.func_closure) @generatorize def f(): while True: return 1 def g(): while True: yield 1 print g() print f() import itertools print list(itertools.islice(f(), 5)) </code> The hardest part was to find the enumerate() bug. I agree with Steven that converting between functions and generators by replacing return with yield and vice versa is hardly ever useful, though. Peter -- http://mail.python.org/mailman/listinfo/python-list