我最近比较了[]
和list()
的处理速度,并惊讶地发现[]
运行速度比list()
快三倍以上。 {}
和dict()
进行了相同的测试,结果实际上是相同的: []
和{}
都花费了约 0.128sec / 百万个周期,而list()
和dict()
花费了约 0.428sec / 百万个周期。
为什么是这样? Do []
和{}
(可能还有()
和''
)也立即传回一些空股票文字的副本,同时使用它们的显式命名副本( list()
, dict()
, tuple()
, str()
)完全创建对象,无论它们实际上是否包含元素?
我不知道这两种方法有何不同,但我很想找出答案。我在文档中或 SO 上都找不到答案,而寻找空括号却比我预期的要麻烦得多。
timeit.timeit("[]")
和timeit.timeit("list()")
以及timeit.timeit("{}")
和timeit.timeit("dict()")
获得计时结果。分别比较列表和字典。我正在运行 Python 2.7.9。
我最近发现 “为什么 True 慢于 if 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
(已通过全局命名空间,以及以搜索builtins
模块),接着是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
因此,每 1 千万次调用必须调用对象额外花费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
>>> dis.dis(lambda: list())
1 0 LOAD_GLOBAL 0 (list)
3 CALL_FUNCTION 0
6 RETURN_VALUE
>>> dis.dis(lambda: [])
1 0 BUILD_LIST 0
3 RETURN_VALUE
由于list
是一个功能转化说一个字符串列表对象,而[]
用于创建一个列表蝙蝠。尝试以下操作(可能对您更有意义):
x = "wham bam"
a = list(x)
>>> a
["w", "h", "a", "m", ...]
尽管
y = ["wham bam"]
>>> y
["wham bam"]
为您提供包含您所输入内容的实际列表。