Life is Long, Use Python

comp
@python
en

Random Python benchmarks. Is Python fast yet 🐍?

Keyword Args of Partial Functions

TL;DR

Binding keyword arguments in functools.partial is slower than raw calls.

def f(a1, a2, a3, a4, a5, a6, a7):
    return sum([a1, a2, a3, a4, a5, a6, a7])

# Raw
f(1, a2=2, a3=3, a4=4, a5=5, a6=6, a7=7)

# Partial
f_partial = functools.partial(f, a2=2, a3=3, a4=4, a5=5, a6=6, a7=7)
f_partial(1)

# Spread
kwargs = {"a2": 2, "a3": 3, "a4": 4, "a5": 5, "a6": 6, "a7": 7}
f(1, **kwargs)
ImplTime (s)
Python (Raw)0.135
Python (Partial)0.237
Python (Spread)0.213

In Python, keyword arguments **kwargs are potentially mutable within the function body.

def why_you_have_to_do_this(a, **kwargs):
    kwargs["a"] += a

Therefore, each call to the function has to create a new dict to store all keyword arguments. This copy also happens when using functools.partial. There is no performance gain compared to simply spreading a dict of arguments in the call, yet you have to pay for the overhead of merging arguments when using partial.

Python Dictionary Literals and Constructors

TL;DR

Use literals to create Python dicts instead of constructors.

One difference between JavaScript and Python is that JavaScript Object literals do not require quoting their keys, but Python dicts do.

let d = { a: 1, b: 2, [some_var]: 3 }
d = { "a": 1, "b": 2, some_var: 3 }

This requires more typing when using dicts as structs. However, Python also supports defining dictionaries using the dict constructor if no keys are variables:

a = dict(a=1, b=2)

What about their speed? Benchmarking these two ways by creating 10^7^ dicts with the same 4 key-value pairs.

MethodSpeed (seconds)
Literal0.618
Constructor0.821

Sadly the constructor is slightly slower. If you look at the constructor definition at dict_new of CPython source, the keyword arguments of the constructor are gathered as a dict first, and then merged to an empty dict which is the one we are constructing. This creates a small overhead.