Python: A better way to write n compositions of a function?

怎甘沉沦 提交于 2021-02-18 18:04:21

问题


I wrote a function "rep" that takes a function f and takes n compositions of f. So rep(square,3) behaves like this: square(square(square(x))). And when I pass 3 into it, rep(square,3)(3)=6561.

There is no problem with my code, but I was wondering if there was a way to make it "prettier" (or shorter) without having to call another function or import anything. Thanks!

def compose1(f, g):
    """Return a function h, such that h(x) = f(g(x))."""
    def h(x):
        return f(g(x))
    return h

def rep(f,n):
    newfunc = f
    count=1
    while count < n:
        newfunc = compose1(f,newfunc)
        count+=1
    return newfunc

回答1:


If you're looking for speed, the for loop is clearly the way to go. But if you're looking for theoretical academic acceptance ;-), stick to terse functional idioms. Like:

def rep(f, n):
    return f if n == 1 else lambda x: f(rep(f, n-1)(x))



回答2:


def rep(f, n):
    def repeated(x):
        for i in xrange(n):
            x = f(x)
        return x
    return repeated

Using a for loop instead of while is shorter and more readable, and compose1 doesn't really need to be a separate function.




回答3:


While I agree that repeated composition of the same function is best done with a loop, you could use *args to compose an arbitrary number of functions:

def identity(x):
    return x

def compose(*funcs):
    if funcs:
        rest = compose(*funcs[1:])
        return lambda x: funcs[0](rest(x))
    else:
        return identity

And in this case you would have:

def rep(f,n):
    funcs = (f,)*n # tuple with f repeated n times
    return compose(*funcs)

And as DSM kindly pointed out in the comments, you could remove the recursion like so:

def compose(*funcs):
    if not funcs:
        return identity
    else:
        def composed(x):
            for f in reversed(funcs):
                x = f(x)
            return x
        return composed

(also note that you can replace x with *args if you also want to support arbitrary arguments to the functions you're composing, but I left it at one argument since that's how you have it in the original problem)




回答4:


Maybe someone will find this solution useful

Compose number of functions

from functools import reduce

def compose(*functions):
    return reduce(lambda x, y: (lambda arg: x(y(arg))), functions)

Use list comprehensions to generate list of functions

def multi(how_many, func):
    return compose(*[func for num in range(how_many)])

Usage

def square(x):
    return x * x

multi(3, square)(3) == 6561 


来源:https://stackoverflow.com/questions/20852263/python-a-better-way-to-write-n-compositions-of-a-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!