[Python-ideas] PEP 572: Statement-Local Name Bindings

Chris Angelico rosuav at gmail.com
Thu Mar 1 01:47:59 EST 2018


On Thu, Mar 1, 2018 at 3:54 PM, Nick Coghlan <ncoghlan at gmail.com> wrote:
> On 1 March 2018 at 06:00, Chris Angelico <rosuav at gmail.com> wrote:
>>
>> On Thu, Mar 1, 2018 at 6:35 AM, Brendan Barnwell <brenbarn at brenbarn.net>
>> wrote:
>> > On 2018-02-28 07:18, Chris Angelico wrote:
>> >>
>> >> Except that assignment is evaluated RHS before LHS as part of a single
>> >> statement. When Python goes to look up the name "a" to store it (as
>> >> the final step of the assignment), the SLNB is still active (it's
>> >> still the same statement - note that this is NOT expression-local), so
>> >> it uses the temporary.
>> >
>> >
>> >         Wait, so you're saying that if I do
>> >
>> > a = (2 as a)
>> >
>> >         The "a = " assignment assigns to the SLNB, and so is then
>> > discarded
>> > after the statement finishes?
>> >
>> >         That seems very bad to me.  If there are SLNBs with this special
>> > "as" syntax, I think the ONLY way to assign to an SLNB should be with
>> > the
>> > "as" syntax.  You shouldn't be able to assign to an SLNB with regular
>> > assignment syntax, even if you created an SNLB with the same name as the
>> > LHS
>> > within the RHS.
>>
>> That seems a reasonable requirement on the face of it, but what about
>> these variants?
>>
>> a = (x as a)
>> a[b] = (x as a)
>> b[a] = (x as a)
>> a[b].c = (x as a)
>> b[a].c = (x as a)
>>
>> Which of these should use the SLNB, which should be errors, which
>> should use the previously-visible binding of 'a'?
>
>
> This is the kind of ambiguity of intent that goes away if statement locals
> are made syntactically distinct in addition to being semantically distinct:
>
>   .a = (2 as .a) # Syntax error (persistent bindings can't target statement
> locals)
>   a = (2 as .a) # Binds both ".a" (ephemerally) and "a" (persistently) to
> "2"
>   .a[b] = (x as .a) # Syntax error (persistent bindings can't target
> statement locals)
>   b[.a] = (x as .a) # LHS references .a
>   .a[b].c = (x as .a) # Syntax error (persistent bindings can't target
> statement locals)
>   b[.a].c = (x as .a) # LHS references .a
>
> We may still decide that even the syntactically distinct variant poses a net
> loss to overall readability, but I do think it avoids many of the
> confusability problems that arise when statement locals use the same
> reference syntax as regular variable names.

Okay. I think I have the solution, then. One of two options:

1) SLNBs are not permitted as assignment (incl augassign) targets.
Doing so is a SyntaxError.
2) SLNBs are ignored when compiling assignment targets. Doing so will
bind to the "real" name.

Using an SLNB to subscript another object is perfectly acceptable, as
that's simply referencing. The only case that might slip between the
cracks is "a[b].c" which technically is looking up a[b] and only
assigning to *that* object (for instance, if 'a' is a tuple and 'b' is
zero, it's perfectly legal to write "a[b].c = 1" even though tuples
are immutable). Other than that, the intention given in all your
examples would be sustained.

Which of the two is preferable? I'm thinking of going with option 2,
but there are arguments on both sides.

ChrisA


More information about the Python-ideas mailing list