def getcomposer(nfunc, _cache={}):
    "getcomposer(n) -> lambda f1, ..., fn:(lambda x: f1(...fn(x)...))"
    try:
        return _cache[nfunc]
    except KeyError:
        fnames = ['f%s' % i for i in range(nfunc)]
        call = ''.join('%s(' % f for f in fnames)
        args = ','.join(fnames)
        cstr = 'lambda %s:(lambda x:%sx%s)' % (args, call, ')'*nfunc)
        composer = _cache[nfunc] = eval(cstr)
        return composer

def compose(*functions):
    "compose(f1, ..., fn) -> lambda x: f1(f2(...fn(x)...))"
    return getcomposer(len(functions))(*functions)

# Test
def double(x): return 2*x
def square(x): return x**2
def succ(x): return x+1

f1 = compose(double, square, succ, float)
f2 = lambda x: double(square(succ(float(x))))

def benchmark(f, n=1000000):
    from time import time
    from itertools import imap
    t0 = time()
    for _ in imap(f1, xrange(n)): pass
    t1 = time()
    return t1-t0

print 'compose', benchmark(f1)
print 'lambda', benchmark(f2)