开发者

Why are list(), dict(), and tuple() slower than [], {}, and ()?

I've recently looked into using list(), dict(), tuple() in place of [], {}, and (), respectively when needing to create an empty one of of the three. The reasoning is that it seemed more readable. I was going to 开发者_如何学Goask for opinions on the style, but then I decided to test performance. I did this:

>>> 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

I tried dict(), tuple() and list() and the function call version of each was incredibly worse than the syntactical version ({} [], ()) So, I have 3 questions:

  1. Why are the function calls more expensive?
  2. Why is there so much difference?
  3. Why the heck does it take 1.2 seconds to create 5 empty lists in my timer? I know timeit turns off garbage collection, but that couldn't possibly have an effect when considering I only used range(5).


the function call requires a variable name lookup, followed by a function invocation. the function called then creates a list and returns it. The list syntax literal gets the interpreter to just make a list:

>>> 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        
>>>


To answer #3.

timeit actually repeats your program 1 000 000 times by default. So in fact, you are creating 5 million lists in 1.2 seconds.


  >>> 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        


Scope lookups are required in order to find dict, tuple, and list, and multiple scopes need to be searched in order to find them. With the syntactic sugar the compiler can know that a specific object needs to be created and so can emit the proper bytecode to do so.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜