Coroutines and argument tupling

Marshall T. Vandegrift llasram at gmail.com
Wed Aug 15 15:58:03 EDT 2007


Hi,

I'm trying to write a decorator which allows one to produce simple
coroutines by just writing a function as a generator expression which
re-receives it's arguments as a tuple from each yield.  For example:

    @coroutine
    def nextn(n=1):
        values = []
        for i in itertools.count():
            while n <= 0:
                (n,) = (yield values)
                values = []
            values.append(i)
            n = n - 1
    
    print nextn()     # => [0]
    print nextn(3)    # => [1, 2, 3]
    print nextn(n=2)  # => [4, 5]
    print nextn()     # => [6]

I've got this working, but have two questions.  First, is there a better
way to generically transform function arguments into a tuple than I'm
doing now?  That way being with this pretty hideous chunk of code:

    class ArgPacker(object):
        def __init__(self, function):
            args, varargs, varkw, defaults = inspect.getargspec(function)
            self.args = args or []
            self.varargs = (varargs is not None) and 1 or 0
            self.varkw = (varkw is not None) and 1 or 0
            self.nargs = len(self.args) + self.varargs + self.varkw
            defaults = defaults or []
            defargs = self.args[len(self.args) - len(defaults):]
            self.defaults = dict([(k, v) for k, v in izip(defargs, defaults)])
    
        def pack(self, *args, **kwargs):
            args = list(args)
            result = [None] * self.nargs
            for i, arg in izip(xrange(len(self.args)), self.args):
                if args:
                    result[i] = args.pop(0)
                elif arg in kwargs:
                    result[i] = kwargs[arg]
                    del kwargs[arg]
                elif arg in self.defaults:
                    result[i] = self.defaults[arg]
                else:
                    return None
            if self.varargs:
                result[len(self.args)] = args
            elif args:
                return None
            if self.varkw:
                result[-1] = kwargs
            elif kwargs:
                return None
            return tuple(result)

I also tried a version using exec, which was much tighter, but used
exec.

Second, am I trying to hammer a nail with a glass bottle here?  The
ugliness of the ArgPacker class makes me suspect that I should perhaps
just manually create and track a generator when I need a function with
generator-like properties.

Thanks!

-Marshall




More information about the Python-list mailing list