Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/349.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的性能';s控制流语句_Python_Loops_For Loop_While Loop - Fatal编程技术网

python的性能';s控制流语句

python的性能';s控制流语句,python,loops,for-loop,while-loop,Python,Loops,For Loop,While Loop,我正在阅读Python维基,上面写着 在2.0版的Python中也添加了列表理解。它们提供了一种在语法上更紧凑、更高效的方式来编写上述for循环: 然而,我发现当我测试这个时,我得到了一些意想不到的结果 In [22]: def while_loop(n): ...: i = 0 ...: while i < n: ...: i+=1 ...: In [23]: def while_loop_2(n): ...:

我正在阅读Python维基,上面写着

在2.0版的Python中也添加了列表理解。它们提供了一种在语法上更紧凑、更高效的方式来编写上述for循环:

然而,我发现当我测试这个时,我得到了一些意想不到的结果

In [22]: def while_loop(n):
    ...:     i = 0
    ...:     while i < n:
    ...:         i+=1
    ...:

In [23]: def while_loop_2(n):
    ...:     while n > 0:
    ...:         n-=1
    ...:

In [24]: def for_loop(n):
    ...:     for _ in range(n):
    ...:         pass
    ...:

In [30]: %timeit(for_loop(1000000))
10 loops, best of 3: 23.9 ms per loop

In [31]: %timeit(while_loop(1000000))
10 loops, best of 3: 37.1 ms per loop

In [32]: %timeit(while_loop_2(1000000))
10 loops, best of 3: 38 ms per loop

In [33]: %timeit([1 for _ in range(1000000)])
10 loops, best of 3: 43.2 ms per loop
[22]中的
:定义while_循环(n):
…:i=0
…:当我0时:
…:n-=1
...:
[24]中:_循环的定义(n):
…:对于范围内的u(n):
…:通过
...:
在[30]:%timeit(对于_循环(1000000))
10个环路,最佳3个:每个环路23.9毫秒
在[31]:%timeit(while_loop(1000000))
10个回路,最佳3个:每个回路37.1毫秒
在[32]:%timeit(while_loop_2(1000000))
10个回路,最好为3:38 ms/回路
在[33]:%timeit([1代表范围内(1000000)])
10个回路,最佳3个:每个回路43.2毫秒
这就引出了一些问题:

  • 为什么
    for
    循环比列表理解快得多?(速度几乎是原来的两倍)

  • 为什么
    while_loop_2
    while_loop
    慢?为什么计数器递增与递减的差异会产生速度上的差异?我的天真让我相信代码行数越少=速度越快-显然不是这样

  • 编辑: 这是在Python2.7中完成的。在3.6中
    while\u loop\u 2
    实际上比
    while\u loop
    更快。新问题是:

  • Python 2.7和3.x之间的
    while
    循环有什么不同

  • 作为序言,您应该知道您的“比较”应该单独分析(而不是相互比较),因为

  • for循环是一个固定的迭代器,在其体内什么都不做
  • while循环在其主体中执行递减/递增,以及
  • 列表理解不仅仅是一个
    for
    循环,因此,我开始回答问题1

  • #1,因为
    for
    循环迭代。列表理解会迭代,并在内存中创建一个列表。当然,这会增加所需的总时间。单凭这一点就足以说服您,但如果不是这样,请查看已反汇编的字节码,看看每个字节码都在做什么。您可以使用
    dis
    模块执行此操作。我实际上用dis来回答你的第三个问题


    #2,至于这个,我无法在python3.6上复制

    %%timeit
    i = 0; n = 100000
    while i < n: i += 1
    
    11.5 ms ± 65.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
    
    通常,基于减量的循环应该快一点,因为与0(
    n>0
    )的比较通常比与非零值(
    i
    )的比较快。但是三角洲通常是“认真的,不要担心”有点小


    要回答第三个问题,我们需要挖掘一下。让我们看看字节码

    import dis
    
    蟒蛇3.6

    蟒蛇2.7

    dis.dis(
    ''n=100000
    当n>0:n-=1''时
    )
    0向前跳15648(到15651)
    3片+2片
    4.
    5.
    6.
    7.
    8.
    9
    10一元正
    11继续循环26984
    14导入-单元名称8293(8293)
    17片+2片
    18向前跳15904(至15925)
    21片+2
    22
    23就地分水岭
    24片+2
    25向前跳11552(到11580)
    28删除子项CR
    29片+2
    30
    

    请注意,生成的字节码之间存在巨大差异。区别就在这里。

    您忘了在链接中测试上面的
    循环:

    newlist = []
    for word in oldlist:
        newlist.append(word.upper())
    

    带列表附加的迭代:

    In [104]: %%timeit
         ...: alist = []
         ...: for i in range(10000):
         ...:    alist.append(i)
         ...: 
    1.07 ms ± 10.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    
    等价表理解

    In [105]: timeit [i for i in range(10000)]
    491 µs ± 20.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    
    这确实比list-append循环快

    从范围对象创建相同的列表:

    In [106]: timeit list(range(10000))
    265 µs ± 679 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    
    不执行任何操作迭代:

    In [107]: %%timeit
         ...: for i in range(10000):
         ...:    pass
         ...: 
    273 µs ± 9.15 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    
    其他一些列表创建:

    In [109]: timeit list(map(lambda i:i, range(10000)))
    1.41 ms ± 3.12 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    In [110]: timeit list(i for i in range(10000))
    784 µs ± 19.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    

    #1的原因是,您的列表理解还创建了一个新的列表(这会带来成本),因此它与普通for循环的比较并不是判断列表理解性能的有效方法。相反,您应该将列表理解与创建列表的其他模式进行比较您的
    for_loop():pass
    与执行增广赋值的两个while循环不公平比较。将列表comp与范围内i的
    进行比较…:alist.append(i)
    循环。列表comp返回某种类型的列表,而不仅仅是迭代或计数。但对于类似的任务,速度差异是适度的。@aydow对于#3,我只能推测,因为我不是一个核心开发人员,但2和3之间的许多变化主要与性能有关。。。就我所知,while可能是其中之一。@aydow我认为最大的区别在于字节码是如何生成的。使用
    dis
    ,您可以查看。
    In [106]: timeit list(range(10000))
    265 µs ± 679 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    
    In [107]: %%timeit
         ...: for i in range(10000):
         ...:    pass
         ...: 
    273 µs ± 9.15 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    
    In [109]: timeit list(map(lambda i:i, range(10000)))
    1.41 ms ± 3.12 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    In [110]: timeit list(i for i in range(10000))
    784 µs ± 19.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)