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

Nick Coghlan ncoghlan at gmail.com
Wed Feb 28 23:31:37 EST 2018


On 28 February 2018 at 08:27, Chris Angelico <rosuav at gmail.com> wrote:

> This is a suggestion that comes up periodically here or on python-dev.
> This proposal introduces a way to bind a temporary name to the value
> of an expression, which can then be used elsewhere in the current
> statement.
>
> The nicely-rendered version will be visible here shortly:
>
> https://www.python.org/dev/peps/pep-0572/


Thanks for putting this together!



> Statement-local name bindings can be used in any context, but should be
> avoided where regular assignment can be used, just as `lambda` should be
> avoided when `def` is an option.
>
>
[snip]


>
> 2. The current implementation [1] implements statement-local names using
>    a special (and mostly-invisible) name mangling.  This works perfectly
>    inside functions (including list comprehensions), but not at top
>    level.  Is this a serious limitation?  Is it confusing?
>

It isn't clear to me from the current PEP what the intended lifecycle of
the bound names actually is, especially for compound statements.

Using list comprehensions as your example currently hides that confusion,
since they create an implicit nested scope anyway, so the references will
go away when the list comprehension terminates no matter what.

So I think it would be useful to have some other examples in the PEP to
more explicitly answer that question:

    x = (expr as y)
    assert x == y # Does this pass? Or raise NameError for 'y'?

    if (condition as c):
        assert c # Does this pass? Or raise NameError for 'c'?
    else:
        assert not c # Does this pass? Or raise NameError for 'c'?
    assert c or not c # Does this pass? Or raise NameError for 'c'?

    class C:
        x = (True as y)
    assert C.y # Does this pass? Or raise AttributeError for 'y'?

I think it would also be worth explicitly considering a syntactic variant
that requires statement local references to be explicitly disambiguated
from regular variable names by way of a leading dot:

    result = [[(f(x) as .y), .y] for x in range(5)]

    (.x, (1 as .x), .x) # UnboundLocalError on first subexpression
    (x, (1 as .x), .x) # Valid if 'x' is a visible name

    x = (expr as .y)
    assert x == .y # UnboundLocalError for '.y'

    if (condition as .c):
        assert .c # Passes
    else:
        assert not .c # Passes
    assert .c or not .c # UnboundLocalError for '.c'

    class C:
        x = (True as .y)
    assert C..y # SyntaxError on the second dot

Since ".NAME" is illegal for both variable and attribute names, this makes
the fact statement locals are a distinct namespace visible to readers as
well as to the compiler, and also reduces the syntactic ambiguity in with
statements and exception handlers.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20180301/2579c572/attachment.html>


More information about the Python-ideas mailing list