Random Python benchmarks. Is Python fast yet 🐍?
Keyword Args of Partial Functions
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)
Impl | Time (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
Use literals to create Python dict
s instead of constructors.
One difference between JavaScript and Python is that JavaScript Object
literals do not require quoting their keys, but Python dict
s do.
let d = { a: 1, b: 2, [some_var]: 3 }
d = { "a": 1, "b": 2, some_var: 3 }
This requires more typing when using dict
s 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^ dict
s with the same 4 key-value pairs.
Method | Speed (seconds) |
---|---|
Literal | 0.618 |
Constructor | 0.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.