[Python-ideas] PEP 572: Statement-Local Name Bindings, take three!

Nick Coghlan ncoghlan at gmail.com
Sat Mar 24 05:12:49 EDT 2018


On 24 March 2018 at 14:41, Steven D'Aprano <steve at pearwood.info> wrote:

> On Sat, Mar 24, 2018 at 05:09:54AM +1100, Chris Angelico wrote:
> > >> Just as function-local names shadow global names for the scope of the
> > >> function, statement-local names shadow other names for that statement.
> > >> (They can technically also shadow each other, though actually doing
> this
> > >> should not be encouraged.)
> > >
> > > That seems weird.
> >
> > Which part? That they shadow, or that they can shadow each other?
>
> Shadowing themselves.
>
> I'm still not convinced these should just shadow local variables. Of
> course locals will shadow nonlocals, which shadow globals, which shadow
> builtins. I'm just not sure that we gain much (enough?) to justify
> adding a new scope between what we already have:
>
> proposed statement-local
> local
> nonlocal
> class (only during class statement)
> global
> builtins
>
> I think that needs justification by more than just "it makes the
> implementation easier".
>

Introducing the new scoping behaviour doesn't make the implementation
easier, it makes it harder. However, there are specific aspects of how that
proposed new scope works (like not being visible from nested scopes) that
make the implementation easier, since they eliminate a whole swathe of
otherwise complicated semantic questions :)

At a user experience level, the aim of the scoping limitation is
essentially to help improve "code snippet portability".

Consider the following piece of code:

    squares = [x**2 for x in iterable]

In Python 2.x, you not only have to check whether or not you're already
using "squares" for something, you also need to check whether or not you're
using "x", since the iteration variable leaks.

In Python 3.x, you only need to check for "squares" usage, since the
comprehension has its own inner scope, and any "x" binding you may have
defined will be shadowed instead of being overwritten.

For PEP 572, the most directly comparable example is code like this:

    # Any previous binding of "m" is lost completely on the next line
    m = re.match(...)
    if m:
        print(m.groups(0))

In order to re-use that snippet, you need to double-check the surrounding
code and make sure that you're not overwriting an "m" variable already used
somewhere else in the current scope.

With PEP 572, you don't even need to look, since visibility of the "m" in
the following snippet is automatically limited to the statement itself:

    if (re.match(...) as m):
        print(m.groups(0))
    # Any previous binding of "m" is visible again here, and hence a common
source of bugs is avoided :)

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/20180324/6f8a65b3/attachment.html>


More information about the Python-ideas mailing list