[Python-ideas] ChainMap as a context manager

dag.odenhall at gmail.com dag.odenhall at gmail.com
Mon Aug 8 06:18:53 CEST 2011

On 8 August 2011 06:11, Nick Coghlan <ncoghlan at gmail.com> wrote:
> On Mon, Aug 8, 2011 at 1:43 PM, dag.odenhall at gmail.com
> <dag.odenhall at gmail.com> wrote:
>> To be quite honest I'm not perfectly sure myself; it just seemed like
>> such a natural context manager that I got curious if it was just
>> overlooked or if I was missing something. If it turns out it would
>> make sense it might be good to realize it early before the 3.3
>> release?
> While the enthusiasm is appreciated, it's useful to run through a
> quick sanity check before lobbing an email into the inboxes of all of
> the python-ideas subscribers:
> 1. Do I have a concrete use case in mind?
> 2. If yes, is that use case highly specific to my current problem
> domain, or is it more broadly applicable than that?
> 3. If no, is there a clear inconsistency or wart that presents a
> roadblock to learning the language that the idea would address?
> We're actually fairly conservative about what we add to the core
> language and the standard library, so we greatly prefer ideas that
> have been "battle tested" outside the standard library first. Py3k did
> include a couple of experiments that are still in the process of
> proving themselves (i.e. function annotations and new-style string
> formatting), but such changes are definitely the exception rather than
> the rule.
> In this case, it is trivial for someone to write a
> collections.ChainMap based decorator that works as you describe:
> @contextmanager
> def scope(chain=None):
>    if scope is None:
>        yield ChainMap({})
>    else:
>        yield chain.new_child()
> with scope() as outer:
>    with scope(outer) as inner1:
>        # Manipulate inner1 without affecting outer
> However, that adds no real expressivity and is unlikely to be
> particularly useful in practice, since most lexical scoping problems
> can be handled using *actual* lexical scoping. ChainMap is useful for
> cases like multiple levels of configuration data where the scoping
> occurs at runtime rather than in the source code. Hiding a call
> new_child() inside a context manager just to get an additional level
> of indentation is fairly pointless.

I meant it in-place, so the scope of the context is more than mere indentation:

scope = ChainMap()

scope['foo'] = 1
with scope:
    scope['foo'] = 2
    with scope:
        scope['foo'] = 3
    assert scope['foo'] == 2
assert scope['foo'] == 1

More information about the Python-ideas mailing list