Here's a recipe using reduce:
def power(f, p, myapply = lambda init, g:g(init)):
ff = (f,)*p # tuple of length p containing only f in each slot
return lambda x:reduce(myapply, ff, x)
def square(x):
return x * x
power(square, 2)(3)
#=> 81
I call this power, because this is literally what the power function does, with composition replacing multiplication.
(f,)*p creates a tuple of length p filled with f in every index. If you wanted to get fancy, you would use a generator to generate such a sequence (see itertools) - but note it would have to be created inside the lambda.
myapply is defined in the parameter list so that it is only created once.