2010-11-22 58 views
6

我最近看着需要创建的三个空单时,到位的[]{}()使用list()dict()tuple(),分别。理由是它看起来更具可读性。我打算征求对这种风格的意见,但后来我决定测试性能。我这样做:为什么list(),dict()和tuple()比[],{}和()慢?

>>> from timeit import Timer 
>>> Timer('for x in range(5): y = []').timeit() 
0.59327821802969538 
>>> from timeit import Timer 
>>> Timer('for x in range(5): y = list()').timeit() 
1.2198944904251618 

我试过dict()tuple()list()和每个函数调用的版本是令人难以置信的比语法版本({}[]())那么差,我有3个问题:

  1. 为什么函数调用更昂贵?
  2. 为什么这么差?
  3. 为什么在我的计时器中创建5个空列表需要1.2秒?我知道timeit关闭了垃圾回收功能,但是在考虑我仅使用range(5)时,这可能不会起作用。
+0

回复:风格意见 - 我经常使用[]。我认为这很清楚。性能问题虽然很有趣。 – nmichaels 2010-11-22 02:32:00

+0

有很多东西看起来很奇怪,直到你习惯了它们。因为list()实际上可能不是'__builtins __。list',所以我会一直比较喜欢'[]'到'list()'。买家要当心。 – SingleNegationElimination 2010-11-22 02:39:12

回答

18

函数调用需要变量名称查找,然后是函数调用。调用的函数然后创建一个列表并返回它。该列表的语法文字得到解释器只是做一个列表:

>>> import dis 
>>> foo = lambda :[] 
>>> bar = lambda :list() 
>>> dis.dis(foo) 
    1   0 BUILD_LIST    0 
       3 RETURN_VALUE   
>>> dis.dis(bar) 
    1   0 LOAD_GLOBAL    0 (list) 
       3 CALL_FUNCTION   0 
       6 RETURN_VALUE   
>>> 
0

范围查找需要,以便找到dicttuple,并list,以及多个领域需要为了找到它们进行搜索。使用语法糖时,编译器可以知道需要创建特定的对象,因此可以发出适当的字节码来执行此操作。

+1

'[]'对于任何东西都不是语法糖。这是一个列表文字。 – SingleNegationElimination 2010-11-22 02:33:20

+0

@TokenMacGuy:确实是句法糖。列表可以通过调用'list()'来生成,但编译器会在适当的上下文中将方括号解释为创建列表。 – 2010-11-22 02:35:01

+2

编译器在遇到'[]'时不会*调用'list()'。看到我的答案。 – SingleNegationElimination 2010-11-22 02:36:39

2
>>> from dis import dis 

    >>> dis(lambda: list()) 
    1   0 LOAD_GLOBAL    0 (list) 
       3 CALL_FUNCTION   0 
       6 RETURN_VALUE   

    >>> dis(lambda: []) 
    1   0 BUILD_LIST    0 
       3 RETURN_VALUE   
5

要回答#3。

timeit默认重复您的程序1 000 000次。所以实际上,你在1.2秒内创建500万个列表。

+0

谢谢。我想下次我应该RTFM :) – orokusaki 2010-11-22 02:50:37

相关问题