On Mon, Oct 25, 2021 at 05:23:38AM +1100, Chris Angelico wrote:
> On Mon, Oct 25, 2021 at 4:29 AM Erik Demaine <[email protected]> wrote:
> >
> > On Sun, 24 Oct 2021, Erik Demaine wrote:
> >
> > > I think the semantics are easy to specify: the argument defaults get
> > > evaluated for unspecified order, in left to right order as specified in
> > > the
> > > def. Those may trigger exceptions as usual.
> >
> > Sorry, that should be:
> >
> > I think the semantics are easy to specify: the argument defaults get
> > evaluated
> > for unspecified ARGUMENT(s), in left to right order as specified in the def.
> > Those may trigger exceptions as usual.
>
> Ah, but is it ALL argument defaults, or only those that are
> late-evaluated? Either way, it's going to be inconsistent with itself
> and harder to explain. That's what led me to change my mind.
The rules for applying parameter defaults are well-defined. I would have
to look it up to be sure, but by memory the rules are:
1. apply positional arguments from left to right;
- if there are more positional arguments than parameters, raise;
2. apply named keyword arguments to parameters:
- if the parameter already has a value, raise;
- if the keyword parameter doesn't exist, raise;
3. for any parameter still without a value, fetch its default;
- if there is no default, then raise.
I would say that it makes most sense to assign early-bound defaults
first, then late-bound defaults, specifically so that late-bound
defaults can refer to early-bound ones:
def func(x=0, @y=x+1)
So step 3 above should become:
3. for any parameters still without a value, skip those which
are late-bound, and fetch the default of the others;
- if there is no default, then raise;
4. for any parameters still without a value, which will all be
late-bound, run from left-to-right and evaluate the default.
This will be consistent and understandable, and if you get an
UnboundLocalError, the cause should be no more confusing than
any other UnboundLocalError.
Note that step 4 (evaluating the late-bound defaults) can raise *any*
exception at all (it's an arbitrary expression, so it can fail in
arbitrary ways). I see no good reason for trying to single out
UnboundLocalError for extra protection by turning it into a syntax
error.
--
Steve
_______________________________________________
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/434CQYGRBVOIRAOJAWCPAVSVPD57RA6B/
Code of Conduct: http://python.org/psf/codeofconduct/