[Python-Dev] performance of {} versus dict(), de fmd(**kw): return kw trumps all ; -)

Łukasz Rekucki lrekucki at gmail.com
Thu Nov 15 10:22:50 CET 2012


Hi,

I posted this (by accident) off the list:

> On 2012-11-14, at 23:43 , Chris Withers wrote:
>
>> On 14/11/2012 22:37, Chris Withers wrote:
>>> On 14/11/2012 10:11, martin at v.loewis.de wrote:
>>>> def xdict(**kwds):
>>>>   return kwds
>>>
>>> Hah, good call, this trumps both of the other options:
>>>
>>> 1000000 -r 5 -v 'def md(**kw): return kw; md(a=1,b=2,c=3,d=4,e=5,f=6,g=7)'
>>> raw times: 0.548 0.533 0.55 0.577 0.539
>>> 1000000 loops, best of 5: 0.533 usec per loop

No, this just doesn't execute the right code:

>>> def md(**kw): return kw; md(a=1,b=2,c=3,d=4,e=5,f=6,g=7)
...
>>> import dis
>>> dis.dis(md)
  1           0 LOAD_FAST                0 (kw)
              3 RETURN_VALUE
              4 LOAD_GLOBAL              0 (md)
              7 LOAD_CONST               1 ('a')
             10 LOAD_CONST               2 (1)
             13 LOAD_CONST               3 ('b')
             16 LOAD_CONST               4 (2)
             19 LOAD_CONST               5 ('c')
             22 LOAD_CONST               6 (3)
             25 LOAD_CONST               7 ('d')
             28 LOAD_CONST               8 (4)
             31 LOAD_CONST               9 ('e')
             34 LOAD_CONST              10 (5)
             37 LOAD_CONST              11 ('f')
             40 LOAD_CONST              12 (6)
             43 LOAD_CONST              13 ('g')
             46 LOAD_CONST              14 (7)
             49 CALL_FUNCTION         1792
             52 POP_TOP

Also:

Python 3.2.3 (default, Apr 11 2012, 07:12:16) [MSC v.1500 64 bit
(AMD64)] on win 32
Type "help", "copyright", "credits" or "license" for more information.
>>> dict({1: "foo"}, **{frozenset([2]): "bar"})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: keyword arguments must be strings

While:

Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit
(Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> dict({1: "foo"}, **{2: "bar"})
{1: 'foo', 2: 'bar'}
>>> dict({1: "foo"}, **{frozenset([2]): "bar"})
{1: 'foo', frozenset([2]): 'bar'}

If you're worrying about global lookup, you should stop (in this case):

$ py -3.3 -m timeit -n 1000000 -r 5 -v -s "def xdict(): return dict()" "xdict()"
raw times: 0.477 0.47 0.468 0.473 0.469
1000000 loops, best of 5: 0.468 usec per loop

$ py -3.3 -m timeit -n 1000000 -r 5 -v -s "def xdict(dict=dict):
return dict()" "xdict()"
raw times: 0.451 0.45 0.451 0.45 0.449
1000000 loops, best of 5: 0.449 usec per loop

$ py -3.3 -m timeit -n 1000000 -r 5 -v -s "def xdict(dict=lambda **kw:
kw): return dict()" "xdict()"
raw times: 0.433 0.434 0.435 0.435 0.431
1000000 loops, best of 5: 0.431 usec per loop

$ py -3.3 -m timeit -n 1000000 -r 5 -v -s "def xdict(dict=dict):
return {}" "xdict()"
raw times: 0.276 0.279 0.279 0.277 0.275
1000000 loops, best of 5: 0.275 usec per loop

And using non-empty dicts doesn't change much and the first one is
roughly the sum of the latter two (as expected):

C:\Users\lrekucki>py -3.3  -m timeit -n 1000000 -r 5 -v -s "def
xdict(dict=dict): return dict(a=1, b=2, c=3, d=4, e=5, f=6)" "xdict()"
raw times: 1.72 1.71 1.71 1.71 1.71
1000000 loops, best of 5: 1.71 usec per loop

C:\Users\lrekucki>py -3.3  -m timeit -n 1000000 -r 5 -v -s "def
xdict(dict=lambda **kw: kw): return dict(a=1, b=2, c=3, d=4, e=5,
f=6)" "xdict()"
raw times: 1.01 1.01 1.01 1.01 1.01
1000000 loops, best of 5: 1.01 usec per loop

C:\Users\lrekucki>py -3.3  -m timeit -n 1000000 -r 5 -v -s "def
xdict(dict=dict): return {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f':
6}" "xdict()"
raw times: 0.744 0.736 0.735 0.733 0.733
1000000 loops, best of 5: 0.733 usec per loop


I hope that this helps move python-dev's focus to some more useful discussion.

--
Łukasz Rekucki


More information about the Python-Dev mailing list