Is it safe to rely on Python function arguments evaluation order?

Question:

Is it safe to assume that function arguments are evaluated from left to right in Python?

Reference states that it happens that way but perhaps there is some way to change this order which may break my code.

What I want to do is to add time stamp for function call:

l = []
l.append(f(), time.time())

I understand that I can evaluate the arguments sequentially:

l = []
res = f()
t = time.time()
l.append(res, t)

But it looks less elegant so I’d prefer the first way if I can rely on it.

Asked By: Phoenix

||

Answers:

Yes, Python always evaluates function arguments from left to right.

This goes for any comma seperated list as far as I know:

>>> from __future__ import print_function
>>> def f(x, y): pass
...
>>> f(print(1), print(2))
1
2
>>> [print(1), print(2)]
1
2
[None, None]
>>> {1:print(1), 2:print(2)}
1
2
{1: None, 2: None}
>>> def f(x=print(1), y=print(2)): pass
...
1
2
Answered By: orlp

Quoting from the reference documentation:

Python evaluates expressions from left to right.

So yes, you can count on that (with one exception, see below).

A call (the (...) part after a primary, such as a function name) is just another expression primary, and the arguments for the call are just more expressions.

Note: There is one exception to this rule. When using *expression in a call (to expand an iterable to form additional positional arguments), then this expression is evaluated before any keyword argument expressions:

>>> from itertools import count
>>> def bar(n, r=(), c=count()): print(f'{next(c)}: bar({n!r})'); return r
...
>>> def foo(*args, **kwargs): pass
...
>>> foo(bar('a1'), spam=bar('a2'), *bar('varargs'), **bar('kwargs', {}))
0: bar('a1')
1: bar('varargs')
2: bar('a2')
3: bar('kwargs')

The linked documentation states:

A consequence of this is that although the *expression syntax may appear after explicit keyword arguments, it is processed before the keyword arguments[.]

Answered By: Martijn Pieters