Terry J. Reedy <tjre...@udel.edu> added the comment:

The particular example of left-to-right function evaluation in
https://docs.python.org/3/reference/expressions.html#evaluation-order
is "expr1(expr2, expr3, *expr4, **expr5)".

Joshua's claim, without evidence, that "'f(*a(), b=b())' will evaluate b() 
before a()" was false, as shown by Neil with dis and is now, as shown by Irit 
with a code example.

But Neil also showed, again with dis, that a revised discrepancy claim, 
""'f(b=b(), *a())' will evaluate a() before b()", is true, because reversing 
the order of these particular arguments does not reverse the evaluation order.  
The dis today is equivalent to the one 7 years ago, with CALL_FUNCTION_VAR 
expanded to two operations.

dis.dis('f(b=b(), *a())')
  1           0 LOAD_NAME                0 (f)
              2 LOAD_NAME                1 (a)
              4 CALL_FUNCTION            0
              6 LOAD_CONST               0 ('b')
              8 LOAD_NAME                2 (b)
             10 CALL_FUNCTION            0
             12 BUILD_MAP                1
             14 CALL_FUNCTION_EX         1
             16 RETURN_VALUE

Irit's example, carried one step further confirms this.

>>> f(b=b(), *a())
a
b
f

Although I considered SilentGhost's reading of
https://docs.python.org/3/reference/expressions.html#calls
as too 'loose' (evaluation order of function argument *is* defined in general), 
that section address this exact case.

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

I read this as an acknowledgement that this order violates the general rule.

I do wonder whether exception is specific to using a stack machine and 
implementation convenience or whether *all* implementations must follow this 
order.  If C-Python specific, it should be labelled as such.

The doc continues with an example call, for a different 'f', where, unlike 
Irit's 'f', the result is "TypeError: f() got multiple values for keyword 
argument 'a'".  It concludes "It is unusual for both keyword arguments and the 
*expression syntax to be used in the same call, so in practice this confusion 
does not arise."

The problem with mixing unpacking and named values might be even clearer if 
"f(b=1, *(2,1))" were added to the example box.  Perhaps *exp after x=exp 
should be prohibited.

If the exception is not removed from the implementation, then perhaps it should 
be added to the evaluation order section.  Something like

"The one exception is in function calls with *expression after a keyword 
argument: f(x=expr2, *expr1)."

----------
nosy: +gvanrossum

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue23316>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to