On 4 July 2013 05:36, Chris Angelico <ros...@gmail.com> wrote: > On Thu, Jul 4, 2013 at 2:30 PM, Joshua Landau > <joshua.landau...@gmail.com> wrote: >> That said, I'm not too convinced. Personally, the proper way to do >> what you are talking about is creating a new closure. Like: >> >> for i in range(100): >> with new_scope(): >> for i in range(100): >> func(i) >> func(i) # Using i from original loop >> >> But it's not like Python'll ever support that. >> > > def foo(): > for i in range(3): > print("outer",i) > def inner(): > for i in range(4): > print("inner",i) > inner() > print("outer",i) > > That works, but you then have to declare all your nonlocals, and it > hardly reads well.
Stealing concepts shamelessly from http://www.slideshare.net/r1chardj0n3s/dont-do-this-24000445, you can do this: import inspect from contextlib import contextmanager @contextmanager def scope(namespace=None): old_names = inspect.currentframe().f_back.f_back.f_locals.copy() yield names = inspect.currentframe().f_back.f_back.f_locals if namespace is not None: new_names = {k:v for k, v in names.items() if k not in old_names and v is not namespace} namespace.update(**new_names) names.clear() names.update(old_names) So you *can* do: >>> for i in range(3): ... with scope(): ... for i in range(3): ... print("Inner:", i) ... print("Outer", i) Inner: 0 Inner: 1 Inner: 2 Outer 0 Inner: 0 Inner: 1 Inner: 2 Outer 1 Inner: 0 Inner: 1 Inner: 2 Outer 2 :) If you pass scope() a dictionary, all the new variables will get added to it. -- http://mail.python.org/mailman/listinfo/python-list