[Python-Dev] Whatever happened to 'nonlocal x = y'? (original) (raw)

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(*asyncfns): async with trio.opennursery() as nursery: winningvalue = None async def driver(asyncfn): nonlocal winningvalue winningvalue = await asyncfn() # we're done, so cancel competitors nursery.cancelscope.cancel() for asyncfn in asyncfns: nursery.startsoon(driver, asyncfn) 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 asynczip(*aiterables): aiterators = [aiterable.aiter() for aiterable in aiterables] done = False while True: items = [None] * len(aiterators) async def fillin(i): try: items[i] = await aiterators[i].anext() except StopAsyncIteration: nonlocal done done = True async with trio.opennursery() as nursery: for i in range(len(aiterators)): nursery.startsoon(fillin, 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