为什么[]比list()快?

我最近比较了[]和的处理速度,并list()惊讶地发现它的[]运行速度是的三倍以上list()。我跑了相同的测试与{}和dict(),结果几乎相同:[]和{}两个花了大约0.128sec /百万次,而list()和dict()大约花费每个0.428sec /万次。


为什么是这样?不要[]和{}(可能()和'',太)立即传回文字的一些空股票的份,而其明确命名同行(list(),dict(),tuple(),str())完全去创建一个对象,他们是否真的有元素?


我不知道这两种方法有何不同,但我很想找出答案。我在文档中或SO上都找不到答案,而寻找空括号却比我预期的要麻烦得多。


通过分别调用timeit.timeit("[]")和timeit.timeit("list()"),和timeit.timeit("{}")和timeit.timeit("dict()")来比较列表和字典,以获得计时结果。我正在运行Python 2.7.9。


我最近发现“ 为什么True慢于if? ”比较了if Trueto 的性能,if 1并且似乎触及了类似的文字对全局场景;也许也值得考虑。


FFIVE
浏览 704回答 3
3回答

拉莫斯之舞

因为[]和{}是文字语法。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因此,1.00 - 0.31 - 0.30 == 0.39每1000万次调用必须调用该对象花费了额外的几秒钟。您可以通过将全局名称别名为本地名称来避免全局查找成本(使用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成本。

慕尼黑8549860

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"]为您提供包含您所输入内容的实际列表。
打开App,查看更多内容
随时随地看视频慕课网APP