Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python中的迭代函数_Python - Fatal编程技术网

Python中的迭代函数

Python中的迭代函数,python,Python,给定一个函数f()、一个数字x和一个整数N,我要计算列表: y = [x, f(x), f(f(x)), ..., f(f... M times...f(f(x)) ] 在Python中执行此操作的一个明显方法是以下Python代码: y = [x] for i in range(N-1): y.append(f(y[-1])) 但我想知道是否有更好或更快的方法来实现这一点。您可以使用发电机: import itertools def apply_apply(f, x_0):

给定一个函数
f()
、一个数字
x
和一个整数
N
,我要计算列表:

y = [x, f(x), f(f(x)), ..., f(f... M times...f(f(x)) ]
在Python中执行此操作的一个明显方法是以下Python代码:

y = [x]
for i in range(N-1):
    y.append(f(y[-1]))

但我想知道是否有更好或更快的方法来实现这一点。

您可以使用发电机:

import itertools

def apply_apply(f, x_0):
    x = x_0
    while True:
        yield x
        x = f(x)

....

y = list(itertools.islice(apply_apply(f, x), N))
另一种方法是走全功能路线:

from functools import reduce

y = list(reduce(lambda x, f: x + [f(x[-1])], [[x_0]] + [f] * (N - 1)))
作为旁注,这两种解决方案在我的机器上的性能都比公认的解决方案好,发电机为2ms,功能为2ms,雷蒙德代码为4ms,代码为
f=lambda x:x*x
x_0=2
N=20


对于
lambda x:2*x
Raymond的版本,其速度略快于生成器方法,且远快于功能变体。这似乎取决于
f
的复杂性,尽管我不知道如何…

有几种方法可以优化此代码:

  • 使用
    itertools.repeat(None,times)
    可以更快地控制循环的数量(这可以避免在每次迭代中创建新的、未使用的整数对象)

  • 您可以通过将其放入函数或生成器中来提高速度(局部变量比全局变量快)

  • 您可以通过将中间结果保存在变量中来提高速度,从而避免
    [-1]
    索引查找(LOAD\u FAST/STORE\u FAST比LOAD\u CONST-1和BINARY\u SUBSCR更快)

  • 您可以通过使用预定义方法而不是
    y.append
    来提高速度

  • 例如:

    from itertools import repeat
    
    def nest(func, x, times):
         result = [x]
         result_append = result.append
         for _ in repeat(None, times):
             x = func(x)
             result_append(x)
         return result
    
    下面是一个示例调用:

    >>> def double(x):
            return 2 * x
    
    >>> nest(double, 3, 5)
    [3, 6, 12, 24, 48, 96]
    
    以下是显示紧密内环、局部变量使用和绑定方法的反汇编:

    >>> from dis import dis
    >>> dis(nest)
      2           0 LOAD_FAST                1 (x)
                  3 BUILD_LIST               1
                  6 STORE_FAST               3 (result)
    
      3           9 LOAD_FAST                3 (result)
                 12 LOAD_ATTR                0 (append)
                 15 STORE_FAST               4 (result_append)
    
      4          18 SETUP_LOOP              45 (to 66)
                 21 LOAD_GLOBAL              1 (repeat)
                 24 LOAD_CONST               0 (None)
                 27 LOAD_FAST                2 (times)
                 30 CALL_FUNCTION            2
                 33 GET_ITER            
            >>   34 FOR_ITER                28 (to 65)
                 37 STORE_FAST               5 (_)
    
      5          40 LOAD_FAST                0 (func)
                 43 LOAD_FAST                1 (x)
                 46 CALL_FUNCTION            1
                 49 STORE_FAST               1 (x)
    
      6          52 LOAD_FAST                4 (result_append)
                 55 LOAD_FAST                1 (x)
                 58 CALL_FUNCTION            1
                 61 POP_TOP             
                 62 JUMP_ABSOLUTE           34
            >>   65 POP_BLOCK           
    
      7     >>   66 LOAD_FAST                3 (result)
                 69 RETURN_VALUE 
    

    for循环中的行应该是“y.append(f(y[-1])”@Ryaan G:是的,应该是,谢谢。f是什么?也许不需要重复应用函数就可以解决它。简单的例子:def(n):返回n+1有趣的问题:)注意,在Python>=3.3中,有一种基于时间的方法,很难为列表构建代码获得有意义的时间度量。随着列表的增长,会定期调用realloc()。根据碎片的不同,该调用要么是即时的(可用空间溢出),要么是缓慢的(必须复制所有数据)。我本来会发布一个生成器解决方案(没有这些问题),但OP特别要求提供一个列表,并询问如何优化其解决问题的方法。