Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.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 While循环>;比for loop快1000倍?_Python_Performance_Python 3.x_Loops - Fatal编程技术网

Python While循环>;比for loop快1000倍?

Python While循环>;比for loop快1000倍?,python,performance,python-3.x,loops,Python,Performance,Python 3.x,Loops,所以关于for循环和while循环的速度的问题以前已经被问过很多次了。for循环应该更快 但是,当我在Python 3.5.1中测试它时,结果如下: timeit.timeit('for i in range(10000): True', number=10000) >>> 12.697646026868842 timeit.timeit('while i<10000: True; i+=1',setup='i=0', number=10000) >>>

所以关于for循环和while循环的速度的问题以前已经被问过很多次了。for循环应该更快
但是,当我在Python 3.5.1中测试它时,结果如下:

timeit.timeit('for i in range(10000): True', number=10000)
>>> 12.697646026868842
timeit.timeit('while i<10000: True; i+=1',setup='i=0', number=10000)
>>> 0.0032265179766799434
timeit.timeit('对于范围(10000)中的i:True',number=10000)
>>> 12.697646026868842
timeit.timeit('whilei>>3.638794646750142

timeit.timeit('当我创建10k
range()
对象时。这些对象需要一些时间才能实现。然后还必须为这些10k对象创建对象(让
for
循环迭代这些值)。接下来,
for
循环通过调用生成的迭代器来使用迭代器协议。后两个步骤也适用于列表上的
for
循环

但最重要的是,您在
while
循环测试中作弊。
while
循环只需运行一次,因为您从未将
i
重置回
0
(感谢)。实际上,您正在运行一个
循环,总共进行19999次比较;第一个测试运行10k次比较,其余9999个测试运行一次比较。该比较非常快:

>>> import timeit
>>> timeit.timeit('while i<10000: True; i+=1',setup='i=0', number=10000)
0.0008302750065922737
>>> (
...     timeit.timeit('while i<10000: True; i+=1', setup='i=0', number=1) +
...     timeit.timeit('10000 < 10000', number=9999)
... )
0.0008467709994874895
哎呀,一个正确运行的
虽然
实际上是慢的,但你的前提(和我的前提)就在这里

我使用了
pass
,以避免回答有关引用该对象的速度有多快的问题(速度很快,但除此之外)。我的计时速度将比您的机器快6倍

如果您想探索为什么迭代更快,可以在Python中为
for
循环的各个组件计时,首先创建
范围()
对象:

>>> timeit.timeit('range(10000)', number=10000)
0.0036197409499436617
因此,创建10000个
range()
对象比运行单个
循环(循环次数为10k次)所需的时间要长。
range()
对象的创建成本高于整数

这确实涉及到全局名称查找,速度较慢,您可以通过使用
设置=“\u range=range”
然后使用
\u range(1000)
来加快查找速度;这将减少大约1/3的计时

接下来,为此创建一个迭代器;在这里,我将为使用一个本地名称,因为
for
循环不必进行哈希表查找,只需访问C函数即可。在二进制中对内存位置的硬编码引用当然要快得多:

>>> timeit.timeit('_iter(r)', setup='_iter = iter; r = range(10000)', number=10000)
0.0009729859884828329
相当快,但是;
循环迭代10k次所需的时间与单个
相同。因此创建可重用对象的成本很低。C实现速度更快。我们还没有迭代

最后,我们在迭代器对象上调用
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
,调用次数为10k次。这同样在C代码中完成,缓存对内部C实现的引用,但使用a,我们至少可以尝试获得

>>> timeit.timeit('n()', setup='from functools import partial; i = iter(range(10000)); n = partial(i.__next__)', number=10000) * 10000
7.759470026940107
男孩,对
iter(范围(1000))的10k次10k调用。对于
管理的循环,下一个\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

然而,它确实说明了C代码中的循环要快得多,这就是为什么
while
循环在正确执行时实际上要慢得多的原因;在字节码中求整数和进行布尔比较比在C代码中迭代
范围()
要花更多的时间(其中CPU直接在CPU寄存器中进行递增和比较):

>(
…timeit.timeit('9999+1',数字=10000**2)+
…timeit.timeit('9999<10000',数字=10000**2)
... )    
3.695550534990616
正是这些操作使得
循环慢了大约3秒



TLDR:您实际上没有正确地测试
循环。我早就应该注意到这一点。

您的计时不正确,
设置只执行一次,然后所有后续运行的
I
值都是
10000
。请参阅以下文档:

主语句执行的时间数。它执行
setup
语句一次,然后返回执行主语句的次数,以秒为单位作为浮点

另外,通过为每次重复打印
i
进行验证:

>>> timeit('print(i)\nwhile i<10000: True; i+=1',setup='i=0', number=5)
0
10000
10000
10000
10000

我不能很好地得到你得到的时差的规模;创建一个
范围()
object有一个成本,只是没有那么大的成本。即使在Python2上,我也不能让它一直保持到12.7秒。啊,我的笔记本电脑只快了6倍,就是这样。你在运行什么Python?这是一个调试版本,差异更大吗?@Alex Python 3.5.1。我的笔记本电脑速度慢,所以我期望有很长的绝对时间。但是你有很大的差异吗租金相对差异?我的笔记本电脑和Martijn几乎一样。
>>> timeit.timeit('n()', setup='from functools import partial; i = iter(range(10000)); n = partial(i.__next__)', number=10000) * 10000
7.759470026940107
>>> (
...     timeit.timeit('9999 + 1', number=10000 ** 2) +
...     timeit.timeit('9999 < 10000', number=10000 ** 2)
... )    
3.695550534990616
>>> timeit('print(i)\nwhile i<10000: True; i+=1',setup='i=0', number=5)
0
10000
10000
10000
10000
>>> timeit('i=0\nwhile i<10000: True; i+=1', number=10000)
8.416439056396484
>>> timeit('for i in range(10000): True', number=10000)
5.589155912399292