Author terry.reedy
Recipients Joshua.Landau, NeilGirdhar, SilentGhost, gvanrossum, iritkatriel, r.david.murray, terry.reedy
Date 2021-06-16.21:23:58
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1623878638.34.0.630164828833.issue23316@roundup.psfhosted.org>
In-reply-to
Content
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.
History
Date User Action Args
2021-06-16 21:23:58terry.reedysetrecipients: + terry.reedy, gvanrossum, r.david.murray, SilentGhost, Joshua.Landau, NeilGirdhar, iritkatriel
2021-06-16 21:23:58terry.reedysetmessageid: <1623878638.34.0.630164828833.issue23316@roundup.psfhosted.org>
2021-06-16 21:23:58terry.reedylinkissue23316 messages
2021-06-16 21:23:58terry.reedycreate