Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/310.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/17.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/68.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 count()的奇怪执行时间_Python_Python 3.x_List_Performance_Python Internals - Fatal编程技术网

Python count()的奇怪执行时间

Python count()的奇怪执行时间,python,python-3.x,list,performance,python-internals,Python,Python 3.x,List,Performance,Python Internals,守则: from timeit import Timer print(min(Timer('y=x.count(1)',setup='x=[1] * 1000').repeat(number=1000000))) print(min(Timer('y=x.count(0)',setup='x=[1] * 1000').repeat(number=1000000))) 我的机器上的结果: 0.7033228789223358 10.16116041096393 有人能解释为什么第一个病例比第

守则:

from timeit import Timer
print(min(Timer('y=x.count(1)',setup='x=[1] * 1000').repeat(number=1000000))) 
print(min(Timer('y=x.count(0)',setup='x=[1] * 1000').repeat(number=1000000)))
我的机器上的结果:

0.7033228789223358
10.16116041096393

有人能解释为什么第一个病例比第二个病例快得多吗?我希望这两次都是相似的。

这是因为您构建列表对象的方式:

x = [1] * 1000    
这将创建一个仅包含一个对象的列表,引用次数为1000次;列表乘法不会创建值的副本。为了理解为什么这很重要,我们需要看看Python列表是如何计算的

list.count()
循环如下所示,是实现的一个快速Python翻译:

这很简单,对吧?然而,情况并非如此;实际代码使用的是
PyObject\u richcomarebool()
,它是。这真的是:

if elem is value or elem == value:
当所有列表元素都是同一个对象时,身份测试(一个简单的指针相等测试)要快得多:

您可以使用任意随机值复制该值:

>>> from timeit import Timer
min(Timer('y=x.count(v)',setup='import random; v = random.randint(1000, 10000000); x=[v] * 1000').repeat(number=100000))
0.2716284029884264
>>> min(Timer('y=x.count(w)',setup='import random; v = random.randint(1000, 10000000); x=[v] * 1000; w = v + 1').repeat(number=100000))
1.0827720829984173
正如这些数字所示,在测试值相等性之前进行简单的指针比较是很有意义的。这正是Python实现实习生某些经常重用的值的原因,比如小整数(),或者也是有效Python标识符的字符串值


如果这里没有使用一个小整数作为
x.count()
的参数,它就不会工作;因为
1
interned,
x.count(1)
使用的对象也是列表的成员
x[0]是1
是真的。

我的Python 3.6.9在这里不同意-
512是512
返回真的,
1e23是1e23
也是如此,
“a”是“a”
(但奇怪的是
(1,)是(1,)
返回假的)@Błotosmętek:单个表达式值常量被插入。@Błotosmętek:单独的作用域不能重复使用常量,所以
v=(lambda:512)();v为512
。查看
导入dis;dis.dis('512是512')
查看为什么它总是返回
True
。Python可以在很多领域重复使用同一对象,而实现也很乐意这样做。@Błotosmętek:另外,至少在3.7和3.8中,
(1,)是(1,)
也返回true,因为
(1,)
只是与编译的字节码一起存储的另一个常量值。在3.6和更老版本中,这是错误的,因为在3.7中,窥视孔不断折叠的责任被转移到AST Optimizer,后者更聪明。
>>> import random
>>> v = random.randint(1000, 100000000)
>>> x = [v] * 1000
>>> all(value is v for value in x)
True
>>> from timeit import Timer
min(Timer('y=x.count(v)',setup='import random; v = random.randint(1000, 10000000); x=[v] * 1000').repeat(number=100000))
0.2716284029884264
>>> min(Timer('y=x.count(w)',setup='import random; v = random.randint(1000, 10000000); x=[v] * 1000; w = v + 1').repeat(number=100000))
1.0827720829984173