[Python-Dev] Whatever happened to 'nonlocal x = y'?
Guido van Rossum
guido at python.org
Fri Jan 5 18:02:15 EST 2018
I don't like those examples -- "nonlocal foo = bar" sounds like bar is used
as the *initializer*, but it actually is just an assignment that overwrites
the actual initial value. IMO those shouldn't be combined.
On Fri, Jan 5, 2018 at 2:59 PM, Nathaniel Smith <njs at pobox.com> wrote:
> On Fri, Jan 5, 2018 at 7:47 AM, Guido van Rossum <guido at python.org> wrote:
> > I don't recall (though someone with more time might find the discussion
> in
> > the archives or on the tracker). It was never implemented and I think it
> > shouldn't be. So we might as well update the PEP. It wouldn't be
> > particularly useful, since (by definition) the function that declares the
> > nonlocal variable is not its owner, and hence it's unlikely to make
> sense to
> > initialize it here. The same reasoning applies to global BTW.
>
> The reason I got curious and looked into it is that recently I've been
> finding myself using it a lot for passing values back out of
> concurrent functions (examples below). So it does have use cases, but
> I agree that it's not clear how much value is really added by saving a
> line here. Maybe in a year or two if this style catches on as
> idiomatic then it'd be worth revisiting.
>
> #######
>
> Example: run several functions, return the value of the one that
> finishes first (or non-deterministic if several finish at ~the same
> time):
>
> async def race(*async_fns):
> async with trio.open_nursery() as nursery:
> winning_value = None
>
> async def driver(async_fn):
> nonlocal winning_value
> winning_value = await async_fn()
> # we're done, so cancel competitors
> nursery.cancel_scope.cancel()
>
> for async_fn in async_fns:
> nursery.start_soon(driver, async_fn)
>
> return winner
>
> #######
>
> Example: an async iterator version of zip, with concurrent evaluation
> of the different iterators (based on an idea from github user @matham:
> https://github.com/python-trio/trio/issues/393):
>
> async def async_zip(*aiterables):
> aiterators = [aiterable.__aiter__() for aiterable in aiterables]
> done = False
> while True:
> items = [None] * len(aiterators)
>
> async def fill_in(i):
> try:
> items[i] = await aiterators[i].__anext__()
> except StopAsyncIteration:
> nonlocal done
> done = True
>
> async with trio.open_nursery() as nursery:
> for i in range(len(aiterators)):
> nursery.start_soon(fill_in, i)
>
> if done:
> break
>
> yield tuple(items)
>
> -n
>
> --
> Nathaniel J. Smith -- https://vorpus.org
>
--
--Guido van Rossum (python.org/~guido)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20180105/2ea9faeb/attachment.html>
More information about the Python-Dev
mailing list