Terry J. Reedy <tjre...@udel.edu> 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 <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