Skip to content

Instantly share code, notes, and snippets.

@ncoghlan
Last active December 19, 2015 18:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ncoghlan/5996924 to your computer and use it in GitHub Desktop.
Save ncoghlan/5996924 to your computer and use it in GitHub Desktop.
This isn't really news, but just putting some numbers on why relying on passing data in kwargs doesn't generally scale well: there ends up being a lot of implicit copying to avoid accidental mutation of unowned objects. In general, if speed or memory usage matters and you potentially have a lot of entries in a map, avoid using kwargs as the sole…
# Using even one additional keyword arg forces CPython to make an additional copy of the entire original keyword dictionary
$ python3 -m timeit -s "kwds = {str(k):v for k, v in enumerate(range(1000))}" -s "def f(**kwargs): return kwargs" "f(**kwds)"
10000 loops, best of 3: 50.5 usec per loop
$ python3 -m timeit -s "kwds = {str(k):v for k, v in enumerate(range(1000))}" -s "def f(**kwargs): return kwargs" "f(other=1, **kwds)"
10000 loops, best of 3: 82.4 usec per loop
# Using a non-dict subclass forces CPython to copy it to a real dictionary as part of the call
$ python3 -m timeit -s "import collections; kwds = collections.UserDict((str(k), v) for k, v in enumerate(range(1000)))" -s "def f(**kwargs): return kwargs" "f(**kwds)"
1000 loops, best of 3: 573 usec per loop
$ python3 -m timeit -s "import collections; kwds = collections.UserDict((str(k), v) for k, v in enumerate(range(1000)))" -s "def f(**kwargs): return kwargs" "f(other=1, **kwds)"
1000 loops, best of 3: 612 usec per loop
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment