[Python-ideas] A "local" pseudo-function

Tim Peters tim.peters at gmail.com
Sun Apr 29 13:01:49 EDT 2018


[Tim]
>> ...
>> This is the kind of code about which there have been background
>> complaints "forever":
>>
>>      m1 = regexp1.match(line)
>>      m2 = regexp2.match(iine)
>>      if m1 and m2:
>>          do all sorts of stuff with m1 and/or m2,
>>          including perhaps modifying local variables
>>          and/or global variables
>>          and/or nonlocal variables
>>
>> The complaints are of two distinct kinds:
>>
>> 1. "I want to compute m1 and m2 _in_ the `if` test".
>>
>> 2. "I don't want these temp names (m1 and m2) accidentally
>>     conflicting with local names already in scope - if these names
>>     already exist, I want the temp names to shadow their
>>     current bindings until the `if` structure is done".
>>
>> So,
>>
>>      if local(m1=regexp1.match(line),
>>                m2 = regexp2.match(iine),
>>                m1 and m2):
>>
>> intends to address both complaints via means embarrassingly obvious to
>> the most casual observer ;-)


[MRAB <python at mrabarnett.plus.com>]
> How about these:
>
>     local m1, m2:
>         m1 = regexp1.match(line)
>         m2 = regexp2.match(line):
>         if m1 and m2:
>             ...
>
>
>     local m1, m2:
>
>         if (m1 := regexp1.match(line)) and (m2 := regexp2.match(line)):
>
>             ...
>
>     local m1=regexp1.match(line), m2=regexp2.match(line):
>         if m1 and m2:


They address complaint #2 in what seems to me a thoroughly Pythonic
(direct, transparent, no more magical than necessary, easy to read)
way.  They don't address complaint #1 at all, but as you've shown (in
the 2nd spelling)  that isn't _inherently_ tied to complaint #2
(complaint #1 is what PEP 572 addresses).

So _if_ PEP 572 is accepted, adding this form of a compound `local`
statement too would address both of the listed complaints, at the
"cost" of a bit more typing and adding a level of indentation.
Neither of which bother me ;-)

`local()` itself was also intended to address the
even-more-in-the-background recurring desires for an expression (as
opposed to statement) oriented way to use throwaway bindings; e.g.,
instead of

    temp = x + y - z + 1
    r = temp**2 - 1/temp

this instead:

    r = local(t=x + y - z + 1, t**2 - 1/t)

It's not an accident that the shorter `t` is used in the latter than
the former's `temp`:  when people are wary of clobbering names by
accident, they tend to use longer names that say "I'm just a temp -
please don't _expect_ my binding to persist beyond the immediate uses
on the next few lines":.

Anyway, that kind of thing is common n functional languages, where

    "let" pile-of-bindings "in" expression

kinds of constructs are widely used _as_ (sub)expressions themselves.

    local t = x + y - z + 1:
        r = t**2 - 1/t

would be the same semantically, but they'd still complain about the
"extra" typing and the visual "heaviness" of introducing a block for
what they _think_ of as being "just another kind of expression".

The `local()` I brought up was, I think, far too biased _toward_ that
use.  It didn't "play nice" with block-oriented uses short of
excruciatingly deep magic.  Your `local` statement is biased in the
other direction, but that's a Good Thing :-)


More information about the Python-ideas mailing list