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 <n...@pobox.com> wrote: > On Fri, Jan 5, 2018 at 7:47 AM, Guido van Rossum <gu...@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)
_______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com