Terry J. Reedy <[email protected]> added the comment:
The following does not consider keyword-only args with or without defaults. My
understanding is the the compiler does not know or considered the signature of
the function when evaluating the args.
from dis import dis
from itertools import permutations as pm # My first use of this.
for a1, a2, a3, a4 in pm(('a', 'b=b', '*g', '**k')):
s = f"e({a1}, {a2}, {a3}, {a4})"
print(s)
try:
cd = compile(s, '', 'eval')
except SyntaxError as e:
print(e)
continue
dis(cd)
Since positional arg cannot follow keyword arg or keyword arg unpacking and
positional arg unpacking cannot follow keyword arg unpacking, only 5 orders of
'a', 'b=b', '*g', and '**k' are legal.
e(a, b=b, *g, **k) g before b
e(a, *g, b=b, **k) normal
e(a, *g, **k, b=b) normal
e(*g, a, b=b, **k) normal
e(*g, a, **k, b=b) normal
For whatever reason, the byte code is more complicated without function
arguments.
e(a, b=b, *g, **k)
1 0 LOAD_NAME 0 (e)
2 LOAD_NAME 1 (a)
4 BUILD_LIST 1
6 LOAD_NAME 2 (g)
8 LIST_EXTEND 1
10 LIST_TO_TUPLE
12 LOAD_CONST 0 ('b')
14 LOAD_NAME 3 (b)
16 BUILD_MAP 1
18 LOAD_NAME 4 (k)
20 DICT_MERGE 1
22 CALL_FUNCTION_EX 1
24 RETURN_VALUE
The exceptional case essentially says that positional arg unpacking cannot
follow keyword args. This is consistent with the other 3 prohibitions.
Arguments passed by position form one group, those passed by name another. The
nice, simple, and consistent rule is that positional args (and unpacking
thereof) cannot follow keyword args (and unpacking there).
But in this one case, instead of raising SyntaxError like the other 3
prohibited orders, the compiler in effect rewrites* the code in a legal order
-- and then compiles as if written that way. How often does it rewrite code to
make it correct?
I think it would have been better to have stuck with 'positional before
keyword'. Can we consider deprecating something rare and easy to get wrong?
Thinking more, I might prefer leaving the Evaluation Order section alone, as it
is correct with respect to the internal rewrite, and revise the explanation of
the quirk in the function doc. We could deprecate the mis-ordering at least in
the doc.
* After writing this, I notice Neil's suggestion that PEP 8 'prohibit' named
params before iterable (positional) unpacking, so that a fixer program could
literally rewrite in the correct order. I am suggesting that it is useful to
take the viewpoint that the compiler is doing this.
----------
_______________________________________
Python tracker <[email protected]>
<https://bugs.python.org/issue23316>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com