ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python – 为什么[]比list()更快?

2019-09-15 20:57:56  阅读:233  来源: 互联网

标签:python performance list instantiation literals


我最近比较了[]和list()的处理速度,并惊讶地发现[]运行速度比list()快三倍以上.我使用{}和dict()运行相同的测试,结果实际上是相同的:[]和{}都花费了大约0.128秒/百万个周期,而list()和dict()每个花费大约0.428秒/百万个周期.

为什么是这样? Do []和{}(以及可能的()和”也会立即传回一些空库存文字的副本,而它们的明确命名对应物(list(),dict(),tuple(),str())完全去创建一个对象,无论它们是否真的有元素?

我不知道这两种方法有何不同,但我很想知道.
我无法在文档中或在SO上找到答案,搜索空括号结果比我预期的问题更多.

我通过调用timeit.timeit(“[]”)和timeit.timeit(“list()”)和timeit.timeit(“{}”)和timeit.timeit(“dict()”)得到了我的计时结果,分别比较列表和词典.我正在运行Python 2.7.9.

我最近发现了“Why is if True slower than if 1?”,将if与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__ module),然后是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秒.

您可以通过将全局名称别名为locals来避免全局查找成本(使用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成本.

标签:python,performance,list,instantiation,literals
来源: https://codeday.me/bug/20190915/1806089.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有