为什么[]比list()更快?
我最近比较了[]
和list()
的处理速度,并惊讶地发现[]
比list()
运行速度快三倍以上。 我用{}
和dict()
进行了相同的测试,结果几乎相同: []
和{}
都花费了大约0.128秒/百万的周期,而list()
和dict()
花费了大约0.428秒/百万的周期。
为什么是这样? Do []
和{}
(也可能是()
和''
)会立即传回一些空的库存文字的副本,而其明确命名的对应文件( list()
, dict()
, tuple()
, str()
)完全去创建一个对象,不管他们是否真的有元素?
我不知道这两种方法有什么不同,但我很想知道。 我无法在文档或搜索结果中找到答案,搜索空括号的结果证明比我预期的更成问题。
我通过调用timeit.timeit("[]")
和timeit.timeit("list()")
和timeit.timeit("{}")
和timeit.timeit("dict()")
获得我的计时结果,分别比较列表和词典。 我正在运行Python 2.7.9。
我最近发现“为什么如果True比1更慢?” 它将if True
与if 1
的性能进行比较,似乎涉及类似的文字与全球情景; 也许这也值得考虑。
因为[]
和{}
是字面语法。 Python可以创建字节码来创建列表或字典对象:
>>> import dis
>>> dis.dis(compile('[]', '', 'eval'))
1 0 BUILD_LIST 0
3 RETURN_VALUE
>>> dis.dis(compile('{}', '', 'eval'))
1 0 BUILD_MAP 0
3 RETURN_VALUE
list()
和dict()
是独立的对象。 他们的名字需要解决,堆栈必须参与推送参数,帧必须被存储以便稍后检索,并且必须进行调用。 这一切都需要更多时间。
对于空白的情况,这意味着至少有一个LOAD_NAME
(它必须搜索全局名称空间以及__builtin__
模块),然后是CALL_FUNCTION
,它必须保留当前帧:
>>> dis.dis(compile('list()', '', 'eval'))
1 0 LOAD_NAME 0 (list)
3 CALL_FUNCTION 0
6 RETURN_VALUE
>>> dis.dis(compile('dict()', '', 'eval'))
1 0 LOAD_NAME 0 (dict)
3 CALL_FUNCTION 0
6 RETURN_VALUE
您可以使用timeit
分别计时查找名称:
>>> import timeit
>>> timeit.timeit('list', number=10**7)
0.30749011039733887
>>> timeit.timeit('dict', number=10**7)
0.4215109348297119
时间差异可能是字典哈希碰撞。 从调用这些对象的时间中减去这些时间,并将结果与使用文字的时间进行比较:
>>> timeit.timeit('[]', number=10**7)
0.30478692054748535
>>> timeit.timeit('{}', number=10**7)
0.31482696533203125
>>> timeit.timeit('list()', number=10**7)
0.9991960525512695
>>> timeit.timeit('dict()', number=10**7)
1.0200958251953125
因此,不得不调用该对象每1000万次呼叫需要额外的1.00 - 0.31 - 0.30 == 0.39
秒。
您可以通过将全局名称别名为本地名称来避免全局查找成本(使用timeit
设置,绑定到名称的所有内容都是本地的):
>>> timeit.timeit('_list', '_list = list', number=10**7)
0.1866450309753418
>>> timeit.timeit('_dict', '_dict = dict', number=10**7)
0.19016098976135254
>>> timeit.timeit('_list()', '_list = list', number=10**7)
0.841480016708374
>>> timeit.timeit('_dict()', '_dict = dict', number=10**7)
0.7233691215515137
但你永远无法克服CALL_FUNCTION
成本。
list()
需要全局查找和函数调用,但是[]
编译为单个指令。 看到:
Python 2.7.3
>>> import dis
>>> print dis.dis(lambda: list())
1 0 LOAD_GLOBAL 0 (list)
3 CALL_FUNCTION 0
6 RETURN_VALUE
None
>>> print dis.dis(lambda: [])
1 0 BUILD_LIST 0
3 RETURN_VALUE
None
因为list
是一个将字符串转换为列表对象的函数,而[]
用于创建一个列表。 试试这个(对你来说可能更有意义):
x = "wham bam"
a = list(x)
>>> a
["w", "h", "a", "m", ...]
而
y = ["wham bam"]
>>> y
["wham bam"]
给你一个实际的列表,其中包含你放入的任何内容。
链接地址: http://www.djcxy.com/p/833.html