【问题标题】:How to repeat a function n times如何重复一个函数n次
【发布时间】:2011-11-13 15:52:11
【问题描述】:

我正在尝试在 python 中编写一个函数,如下所示:

def repeated(f, n):
    ...

其中f 是一个接受一个参数的函数,n 是一个正整数。

例如,如果我将正方形定义为:

def square(x):
    return x * x

我打电话给

repeated(square, 2)(3)

这将平方 3、2 次。

【问题讨论】:

    标签: python higher-order-functions


    【解决方案1】:

    应该这样做:

     def repeated(f, n):
         def rfun(p):
             return reduce(lambda x, _: f(x), xrange(n), p)
         return rfun
    
     def square(x):
         print "square(%d)" % x
         return x * x
    
     print repeated(square, 5)(3)
    

    输出:

     square(3)
     square(9)
     square(81)
     square(6561)
     square(43046721)
     1853020188851841
    

    lambda-less?

    def repeated(f, n):
        def rfun(p):
            acc = p
            for _ in xrange(n):
                acc = f(acc)
            return acc
        return rfun
    

    【讨论】:

      【解决方案2】:

      使用reduce 和lamba。 以您的参数开始构建一个元组,然后是您要调用的所有函数:

      >>> path = "/a/b/c/d/e/f"
      >>> reduce(lambda val,func: func(val), (path,) + (os.path.dirname,) * 3)
      "/a/b/c"
      

      【讨论】:

        【解决方案3】:

        这样的?

        def repeat(f, n):
             if n==0:
                     return (lambda x: x)
             return (lambda x: f (repeat(f, n-1)(x)))
        

        【讨论】:

        • 它可能确实如此,但我认为它显示了 OP 想要构建的内容。
        • 如果您将检查更改为 n == 0 并返回 lambda x: x 在这种情况下,您的方法也会为零。
        【解决方案4】:

        使用名为 repeatfunc 的 itertools 配方来执行此操作。

        给定

        def square(x):
            """Return the square of a value."""
            return x * x
        

        代码

        来自itertools recipes

        def repeatfunc(func, times=None, *args):
            """Repeat calls to func with specified arguments.
        
            Example:  repeatfunc(random.random)
            """
            if times is None:
                return starmap(func, repeat(args))
            return starmap(func, repeat(args, times))
        

        演示

        可选:您可以使用第三方库more_itertools,它可以方便地实现这些配方:

        import more_itertools as mit
        
        
        list(mit.repeatfunc(square, 2, 3))
        # [9, 9]
        

        通过> pip install more_itertools安装

        【讨论】:

          【解决方案5】:

          使用 reduce 和 itertools.repeat(如 Marcin 建议的那样):

          from itertools import repeat
          from functools import reduce # necessary for python3
          
          def repeated(func, n):
              def apply(x, f):
                  return f(x)
              def ret(x):
                  return reduce(apply, repeat(func, n), x)
              return ret
          

          您可以按如下方式使用它:

          >>> repeated(os.path.dirname, 3)('/a/b/c/d/e/f')
          '/a/b/c'
          
          >>> repeated(square, 5)(3)
          1853020188851841
          

          (分别导入os或定义square后)

          【讨论】:

            【解决方案6】:

            我想你想要函数组合:

            def compose(f, x, n):
              if n == 0:
                return x
              return compose(f, f(x), n - 1)
            
            def square(x):
              return pow(x, 2)
            
            y = compose(square, 3, 2)
            print y
            

            【讨论】:

            • 请注意,OP 要求的是高阶函数。您已经创建了一个重复应用相同函数的递归函数。不太一样。
            • This answer 建议def compose(f, x, n): return functools.reduce( lambda x, _: f(x), range(n), x)
            【解决方案7】:

            这是一个使用 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
            

            我称之为power,因为这实际上是幂函数的作用,用合成代替乘法。

            (f,)*p 创建一个长度为 p 的元组,在每个索引中填充 f。如果您想变得花哨,您可以使用生成器来生成这样的序列(请参阅itertools) - 但请注意,它必须在 lambda 中创建。

            myapply 在参数列表中定义,因此只创建一次。

            【讨论】:

            • 对于大 p,这有显式构造长度为 n 的元组的缺点。
            • @UweKleine-König 是的,这就是 5 年前我提到使用 itertools 生成器作为替代方案的原因。
            猜你喜欢
            • 2021-11-30
            • 1970-01-01
            • 2019-07-22
            • 1970-01-01
            • 2016-04-19
            • 1970-01-01
            • 1970-01-01
            • 2019-02-09
            • 1970-01-01
            相关资源
            最近更新 更多