On Wed, Oct 27, 2021 at 12:59 PM Chris Angelico <[email protected]> wrote:
>
> On Wed, Oct 27, 2021 at 12:50 PM Rob Cliffe <[email protected]> wrote:
> >
> >
> >
> > On 27/10/2021 00:50, Chris Angelico wrote:
> > > On Wed, Oct 27, 2021 at 10:38 AM Rob Cliffe <[email protected]>
> > > wrote:
> > >
> > >> There has been support for evaluating all early-bound defaults before
> > >> all late-bound defaults. I have been persuaded that this is a
> > >> reasonable option. AFAICS there would be little practical difference
> > >> from straight left-to-right evaluation of defaults, since assigning an
> > >> early-bound default should not have a side effect. So it could even be
> > >> an implementation choice.
> > > If it's an implementation choice, then it'll mean that code is legal
> > > on some interpreters and not others. Whether that's a major problem or
> > > not I don't know, but generally, when you can't depend on your code
> > > working on all interpreters, it's not best practice (eg
> > > "open(fn).read()" isn't recommended, even if it happens to close the
> > > file promptly in CPython).
> > >
> > > ChrisA
> > I guess I wasn't clear. I'm not sure if you understood what I meant to
> > say, or not.
> > First I should have said "binding" rather than "evaluating".
> > What I meant was that in cases like
> > def f(a=earlydefault1, b:= latedefault2, c=earlydefault3,
> > d:=latedefault4):
> > it makes no real difference if the bindings are done in the order
> > a, c, b, d (early ones before late ones)
> > or
> > a, b, c, d (strict left-to-right)
> > since binding an early default should have no side effects, so (I
> > thought, wrongly) it could be an implementation detail.
> > Of course there IS a difference: it allows late default values to refer
> > to subsequent early default values, e.g. in the example above
> > `latedefault2' could refer to `c`. So yes, then that code would be
> > legal on some interpreters and not others, as you said. If you
> > understood exactly what I meant, I apologise.
>
> Yep, that's precisely the distinction that matters: whether it's legal
> to refer to parameters further to the right. If we consider tuple
> unpacking as an approximate parallel:
>
> def f():
> a = [10,20,30]
> i, a[i] = 1, "Hi"
Premature send, oops...
def f():
a = [10, 20, 30]
i, a[i] = 1, "Hi"
print(a)
It's perfectly valid to refer to something from earlier in the
multiple assignment, because they're assigned left to right. Python
doesn't start to look up the name 'a' until it's finished assigning to
'i'.
Since Python doesn't really have a concept of statics or calculated
constants, we don't really have any parallel, but imagine that we
could do this:
def f():
# Calculate this at function definition time and then save it
# as a constant
const pos = random.randrange(3)
a = [10, 20, 30]
i, a[i] = pos, "Hi"
This is something what I'm describing. The exact value of an
early-bound argument default gets calculated at definition time and
saved; then it gets assigned to its corresponding parameter if one
wasn't given.
(Actually, I'd really like Python to get something like this, as it'd
completely replace the "random=random" optimization - there'd be no
need to pollute the function's signature with something that exists
solely for the optimization. It'd also make some of these kinds of
things a bit easier to explain, since there would be a concept of
def-time evaluation separate from the argument list. But we have what
we have.)
So I think that we did indeed understand one another.
ChrisA
_______________________________________________
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/CZN7C3N2NON3QBECGRRBYNL7FAJNOPAI/
Code of Conduct: http://python.org/psf/codeofconduct/