拉莫斯之舞
因为[]和{}是文字语法。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成本。